Commit fe07dbb
Fix race condition: pending request registered after reading loop cleanup
When a child process exits immediately, the message reading loop can detect
EOF and complete its cleanup sweep of _pendingRequests before SendRequestAsync
registers the initialize request's TaskCompletionSource. The TCS is then never
signaled, causing McpClient.CreateAsync to hang indefinitely.
Fix: Set a _messageProcessingComplete flag before the sweep, and check it in
SendRequestAsync after registering the TCS. This ensures that either the sweep
finds the TCS, or SendRequestAsync detects the flag and fails the TCS itself.
This race was the root cause of intermittent test host hangs on .NET 9+ in CI,
where short-lived child processes (echo to stderr, exit 1) would exit before
the session initialization request was sent.
Diagnostic evidence:
- xUnit diagnostic log shows the test's async Task starts but never completes
- dumpasync shows zero MCP state machines on the heap (entire chain GC'd)
- Hang only on .NET 9+ (different timing vs .NET 8 avoids the race)
- Always one of the StdioClientTransport stderr callback tests
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>1 parent 2c41608 commit fe07dbb
1 file changed
Lines changed: 16 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
91 | 91 | | |
92 | 92 | | |
93 | 93 | | |
| 94 | + | |
94 | 95 | | |
95 | 96 | | |
96 | 97 | | |
| |||
325 | 326 | | |
326 | 327 | | |
327 | 328 | | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
328 | 332 | | |
329 | 333 | | |
330 | 334 | | |
| |||
569 | 573 | | |
570 | 574 | | |
571 | 575 | | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
572 | 588 | | |
573 | 589 | | |
574 | 590 | | |
| |||
0 commit comments