Commit 7916e99
Add Task.Delay as GC root in ConnectAsync WhenAny
The async chain from ConnectAsync through initializeTask/processingTask
can become GC-unreachable when the server process exits before responding.
Task.Delay creates a System.Threading.Timer that is directly rooted in
the runtime's timer queue, providing a simple GC root chain:
Timer Queue -> Timer -> Task.Delay -> WhenAny -> ConnectAsync.
This ensures ConnectAsync always resumes within the initialization
timeout, even if intermediate state machines are collected.
Use a dedicated CTS for the delay (not the caller's cancellationToken)
so external cancellation flows through initializeTask via
initializationCts, preserving the expected OperationCanceledException
propagation path.
Only call FailPendingRequests when processingTask wins (server exited).
When delayTask wins, let the CancelAfter timer cancel initializationCts
naturally, producing TimeoutException through the existing OCE catch
block.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>1 parent 976f26c commit 7916e99
1 file changed
+36
-8
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
555 | 555 | | |
556 | 556 | | |
557 | 557 | | |
558 | | - | |
559 | | - | |
560 | | - | |
561 | | - | |
562 | | - | |
563 | | - | |
564 | | - | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
565 | 588 | | |
566 | | - | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
567 | 595 | | |
568 | 596 | | |
569 | 597 | | |
| |||
0 commit comments