Commit 0665aaf
Fix DisposeAsync hang by ensuring SetDisconnected after CleanupAsync
StreamClientSessionTransport.DisposeAsync could hang indefinitely when
awaiting Completion because the channel writer was never completed.
Root cause: ReadMessagesAsync and DisposeAsync race to call CleanupAsync.
The _cleanedUp Interlocked guard ensures only one runs the full body
(which calls SetDisconnected to complete the channel). The loser calls
CancelShutdown() and returns immediately — without waiting for the winner
to finish. If DisposeAsync then does 'await Completion', it blocks on a
channel that the still-running cleanup hasn't completed yet.
Fix: call SetDisconnected() after CleanupAsync in DisposeAsync as a
safety net. SetDisconnected is idempotent (uses Interlocked.Exchange),
so a duplicate call is a no-op.
Also removes the instrumented xUnit DLLs and MSBuild target that were
added to test a disproven GC-collection hypothesis.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>1 parent 5d23888 commit 0665aaf
File tree
4 files changed
+10
-19
lines changed- src/ModelContextProtocol.Core/Client
- tests
- Common/InstrumentedXunit
4 files changed
+10
-19
lines changedLines changed: 10 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
97 | 97 | | |
98 | 98 | | |
99 | 99 | | |
100 | | - | |
101 | | - | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
102 | 110 | | |
103 | 111 | | |
104 | 112 | | |
| |||
Binary file not shown.
Binary file not shown.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | 11 | | |
0 commit comments