-
Notifications
You must be signed in to change notification settings - Fork 723
fix(client): potential risk of sending on closed channel #194
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThe update revises the logic for handling Server-Sent Events (SSE) response streams in the client transport layer. The main change is to defer the closure of the response channel until after all SSE events have been processed, rather than closing it immediately after channel creation. This is achieved by launching a goroutine to process the SSE stream and closing the channel only after stream processing is complete. The event unmarshaling and notification handling logic remains unchanged. Changes
Possibly related PRs
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🧰 Additional context used🧬 Code Graph Analysis (1)client/transport/streamable_http.go (1)
🔇 Additional comments (1)
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Note that the local context variable


ctxin funchandleSSEResponse()may be cancelled at any time because its parent context is canceled, and then funchandleSSEResponse()will exit and close channelresponsChan. But it is possible that we are going to write to channelresponsChanin funcreadSSEandpanic: send on closed channelalthough the possibility of this scenario is rather low.[Que1] Is it really has the potential of panic ? Proof is as follows:
In the picture above, we utilized
sync.WaitGroupfor mocking the possible scenario and controlling the execution sequence of cancelling context and sending message toresponseChan, and we will find that the test will fail because ofpanicNow let's see what will happen after change( only test fails, no longer panic):
[Que 2] Why not check
ctxis cancelled or not before we send message toresponseChan:In my opinion, this plan is not particularly rigorous in concurrent scenario. One boundary case is that when both two
casesinselectare ready, GoRuntime chooses the case at random and may choose to send message to closed channelresponseChan, for which we encounter panic again[Que 3] Why not directly
close(responseChan)directly after sending message toresponseChan:I think, this plan is also not rigorous because func
readSSEmay call its argumenthandlerfor zero, one or more than one times, and we can't make sure that it will callhandlerfor exactly once:readSSEcall its argumenthandlerfor more than one times, we will fail because ofpanic: close of closed channelreadSSEdoes not callhandler, we will miss the chance of closingresponseChanthat may bury the risk of resource leakage in the near future?Summary by CodeRabbit