Deterministically cancel background task-store runners on server disposal via a server-lifetime CTS

オープン
#1,707 コメント 1 件 リアクション 0 件 担当者 1 名 GitHub で見る

@jstar0 がすでに取り組んでいます。

2026年7月19日 から。

評価

この issue はまだ評価されていません。

説明

bug enhancement P2 ready for work

Background

While investigating the flaky Windows Debug CI hang (#1701, fixed in #1702), a legitimate — but separate — server-lifetime concern was raised in review that should be addressed on its own.

The real root cause of #1701 turned out to be a client-side server/discover probe timeout being spuriously tripped under CI slowness (fixed test-side in #1702). It was not caused by background task disposal. However, the disposal behavior of background task-store runners is still worth hardening.

Problem

Background task runners in McpServerImpl (the tasks extension / MRTR machinery) are not deterministically cancelled and awaited on server disposal. Each handler currently uses a long-lived, per-handler CancellationTokenSource (see McpServerImpl.cs around the "Create a long-lived CTS for the handler that survives across retries" comment, ~L2120), and disposal cancels the set of runners it knows about at that moment.

This leaves a race: a background task registered after the current cancellation sweep has run can escape cancellation entirely, since disposal has already iterated the collection. Such a runner can outlive the server, which is exactly the kind of dangling background work that can leak into the next test or keep resources alive past DisposeAsync.

Proposed fix

Link every background task-store runner's cancellation to a single server-lifetime CancellationTokenSource that is cancelled at the very start of DisposeAsync (before, or as part of, the existing cancellation sweep). Any runner registered after that point would then be created from an already-cancelled token, so it either never starts meaningful work or exits promptly — closing the register-after-sweep race deterministically.

Concretely:

  • Introduce a server-lifetime CTS on McpServerImpl.
  • Cancel it at the start of disposal.
  • Create each background runner's CancellationTokenSource linked to that server-lifetime token (in addition to any per-request/per-handler token).
  • Ensure disposal awaits outstanding runners after cancelling, so no background task outlives the server.

Context / references

Notes

This is intentionally scoped as a follow-up so #1702 can stay a minimal, test-only fix for the flaky hang. This issue tracks the independent server-lifetime/disposal hardening.

主要言語
C#
スター
4.5k
フォーク
814
平均マージ
9日 19時間
マージ済み PR(30日)
4

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

modelcontextprotocol/csharp-sdk のほかの issue

modelcontextprotocol/csharp-sdk の issue をすべて見る

似ている issue

C# の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。