Commit 9da3f45
Fix race: double-sweep pending requests for non-atomic ConcurrentDictionary
When a server process exits immediately, ProcessMessagesCoreAsync's
reading loop completes and sweeps _pendingRequests to fail them. But
ConcurrentDictionary.GetEnumerator() is non-atomic: it traverses
buckets without locks, so an entry added to an already-traversed bucket
can be missed. This leaves the TCS orphaned and CreateAsync hangs.
Fix by sweeping twice. The second pass catches entries the first pass
missed (nothing modifies those entries between passes). Entries
registered after the _messageProcessingComplete flag is set are
self-handled by SendRequestAsync's flag check.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>1 parent 37976fc commit 9da3f45
8 files changed
Lines changed: 13 additions & 104 deletions
File tree
- .github/workflows
- src/ModelContextProtocol.Core
- Client
- tests
- Common
- InstrumentedXunit
- Utils
- ModelContextProtocol.AspNetCore.Tests
- ModelContextProtocol.Tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
61 | 61 | | |
62 | 62 | | |
63 | 63 | | |
64 | | - | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | 64 | | |
70 | 65 | | |
71 | 66 | | |
| |||
86 | 81 | | |
87 | 82 | | |
88 | 83 | | |
89 | | - | |
90 | 84 | | |
91 | 85 | | |
92 | 86 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
533 | 533 | | |
534 | 534 | | |
535 | 535 | | |
536 | | - | |
| 536 | + | |
537 | 537 | | |
538 | 538 | | |
539 | 539 | | |
| |||
543 | 543 | | |
544 | 544 | | |
545 | 545 | | |
546 | | - | |
| 546 | + | |
547 | 547 | | |
548 | 548 | | |
549 | 549 | | |
| |||
553 | 553 | | |
554 | 554 | | |
555 | 555 | | |
556 | | - | |
557 | | - | |
558 | | - | |
559 | | - | |
560 | | - | |
561 | | - | |
562 | | - | |
563 | | - | |
564 | | - | |
565 | | - | |
566 | | - | |
567 | | - | |
568 | | - | |
569 | | - | |
570 | | - | |
571 | | - | |
| 556 | + | |
572 | 557 | | |
573 | 558 | | |
574 | 559 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
338 | 338 | | |
339 | 339 | | |
340 | 340 | | |
341 | | - | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
342 | 347 | | |
343 | | - | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
344 | 352 | | |
345 | 353 | | |
346 | 354 | | |
| |||
Binary file not shown.
Binary file not shown.
This file was deleted.
Lines changed: 0 additions & 11 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
62 | 62 | | |
63 | 63 | | |
64 | 64 | | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | | - | |
70 | | - | |
71 | | - | |
72 | | - | |
73 | | - | |
74 | | - | |
75 | | - | |
76 | 65 | | |
Lines changed: 0 additions & 11 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
98 | 98 | | |
99 | 99 | | |
100 | 100 | | |
101 | | - | |
102 | | - | |
103 | | - | |
104 | | - | |
105 | | - | |
106 | | - | |
107 | | - | |
108 | | - | |
109 | | - | |
110 | | - | |
111 | | - | |
112 | 101 | | |
0 commit comments