Skip to content

Fix race in KestrelInMemoryConnection #233

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

Merged

Conversation

halter73
Copy link
Contributor

@halter73 halter73 commented Apr 7, 2025

This should avoid the following race. I went the easy route, and just stop disposing KestrelInMemoryConnection._connectionClosedCts, because IIRC, you only really need to dispose it if a caller is using something like CancellationToken.WaitHandle, which I don't expect in our tests at least. I could try synchronizing with the SocketsHttpHandler disposing the stream on a background thread, but it was a lot more code and risked deadlocks if done incorrectly.

[xUnit.net 00:00:06.33]       System.AggregateException : One or more errors occurred. (The CancellationTokenSource has been disposed.)
[xUnit.net 00:00:06.33]     [FATAL ERROR] System.AggregateException
[xUnit.net 00:00:06.33]       ---- System.ObjectDisposedException : The CancellationTokenSource has been disposed.
[xUnit.net 00:00:06.33]       Stack Trace:
[xUnit.net 00:00:06.33]            at System.Threading.CancellationTokenSource.ExecuteCallbackHandlers(Boolean throwOnFirstException)
[xUnit.net 00:00:06.33]            at System.Threading.TimerQueueTimer.Fire(Boolean isThreadPool)
[xUnit.net 00:00:06.33]            at System.Threading.TimerQueue.FireNextTimers()
[xUnit.net 00:00:06.33]            at System.Threading.ThreadPoolWorkQueue.Dispatch()
[xUnit.net 00:00:06.33] Catastrophic failure: System.AggregateException : One or more errors occurred. (The CancellationTokenSource has been disposed.)
[xUnit.net 00:00:06.33]            at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
---- System.ObjectDisposedException : The CancellationTokenSource has been disposed.
[xUnit.net 00:00:06.33]         ----- Inner Stack Trace -----
[xUnit.net 00:00:06.33]            at System.Threading.CancellationTokenSource.Cancel()
[xUnit.net 00:00:06.33]         /_/tests/ModelContextProtocol.Tests/Utils/KestrelInMemoryConnection.cs(83,0): at ModelContextProtocol.Tests.Utils.KestrelInMemoryConnection.DuplexStream.Dispose(Boolean disposing)
[xUnit.net 00:00:06.33]            at System.IO.Stream.Close()
[xUnit.net 00:00:06.33]            at System.Threading.CancellationTokenSource.Invoke(Delegate d, Object state, CancellationTokenSource source)
[xUnit.net 00:00:06.33]            at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
[xUnit.net 00:00:06.33]         --- End of stack trace from previous location ---
[xUnit.net 00:00:06.33]            at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
[xUnit.net 00:00:06.33]            at System.Threading.CancellationTokenSource.ExecuteCallbackHandlers(Boolean throwOnFirstException)

https://github.com/modelcontextprotocol/csharp-sdk/actions/runs/14319353286/job/40132789327

  • Also, this removes some duplication from WithStdioServerTransport and WithStreamServerTransport

@halter73 halter73 requested a review from stephentoub April 7, 2025 21:29
@halter73 halter73 merged commit 3a2e9a2 into modelcontextprotocol:main Apr 7, 2025
7 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants