Replies: 1 comment 1 reply
-
Thanks -- it sounds like you've found a bug: do you want to move this to an issue? |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Pre-submission Checklist
Question Category
Your Question
Description
I have observed a potential issue with goroutine leaks in the
streamableClientConn
implementation when handling Server-Sent Events (SSE). Below is a description of the issue and the potential scenario that may lead to a goroutine leak.go-sdk/mcp/streamable.go
Lines 751 to 770 in c037ba5
Problem Scenario
When the server sends SSE events, a goroutine is spawned to read events and write them to the
s.incoming
channel:Read()
as the Sole Consumer:The
Read()
method is the only consumer ofs.incoming
. IfRead()
exits (due to s.done being closed byClose()
), there will be no remaining consumer fors.incoming
.If
s.incoming
becomes full (due to slow consumption or high-frequency events), the goroutine writing tos.incoming
will block and will not be able to proceed.Close()
Function Call:After
Close()
is called,s.done
is closed, which causes the goroutine runninghandleSSE
to exit. However, the sub-goroutine writing tos.incoming
remains blocked because the channel is full. Sinceresp.Body.Close()
is deferred inhandleSSE
, it is executed when thehandleSSE
goroutine exits, which leads to the closure of the underlying stream.Although
resp.Body.Close()
will cause thefor range
loop inside the goroutine to end when it completes a single iteration, the goroutine remains blocked ats.incoming <- evt.data
within the loop. This prevents the goroutine from proceeding to the next iteration and exiting, thus causing the goroutine to remain in a blocked state, leading to a potential goroutine leak.Proposed Solution:
To resolve this issue, I suggest implementing a solution where the child goroutine listens for both the
done
channel and thes.incoming
channel, ensuring that the goroutine exits if either thedone
channel is closed or if there is a potential blockage on thes.incoming
channel.I am concerned that this could lead to unbounded goroutine accumulation, especially in high-load scenarios.
If I have misunderstood the behavior or missed any important context, I sincerely apologize for any confusion this might cause, and I would be grateful for further clarification. I’m happy to help address this issue if needed and contribute to improving the implementation.
Beta Was this translation helpful? Give feedback.
All reactions