Skip to content

[WIP] Fix flaky task cancellation test hang on Windows Debug CI (#1701)#1702

Draft
PranavSenthilnathan wants to merge 1 commit into
mainfrom
pranavsenthilnathan/fix-task-cancellation-test-hang
Draft

[WIP] Fix flaky task cancellation test hang on Windows Debug CI (#1701)#1702
PranavSenthilnathan wants to merge 1 commit into
mainfrom
pranavsenthilnathan/fix-task-cancellation-test-hang

Conversation

@PranavSenthilnathan

Copy link
Copy Markdown
Contributor

Summary

Fixes #1701TaskTool_CancellationToken_GetTaskShowsWorkingBeforeCancel intermittently causes the xUnit test host to hang for 7+ minutes on Windows Debug CI.

Root Cause

Two issues combine to cause the hang:

1. Test doesn't wait for background tool cancellation before teardown

TaskTool_CancellationToken_GetTaskShowsWorkingBeforeCancel ends with:

await client.CancelTaskAsync(taskId, ct);
// <-- returns here; background Task.Run may still be live

CancelTaskAsync signals the CTS but doesn't wait for the tool body to finish. The sibling test (TaskTool_CancellationToken_FiresWhenExplicitlyCancelled) correctly awaits _toolCancellationFired.Task.WaitAsync(...) first — the flaky test was missing this.

2. Background Task.Run not tracked during server disposal

When a TaskStore is configured, McpServerImpl fires off background Task.Run lambdas to run tools but never tracked or awaited them in DisposeAsync. Under the MRTR-aware path (which is active on the 2026-07-28 protocol with a stateful transport), ObserveHandlerCompletionAsync must decrement _mrtrInFlightCount before DisposeAsync can complete. On Windows in Debug builds, thread-pool scheduling pressure can delay that decrement, causing DisposeAsync to wait on _allMrtrHandlersCompleted — and if the background task itself is also delayed, this manifests as a multi-minute hang.

Fixes

Fix 1 (test): Add await _toolCancellationFired.Task.WaitAsync(TestConstants.DefaultTimeout, ct) after CancelTaskAsync in the flaky test, matching the pattern used by the passing sibling test.

Fix 2 (infrastructure): Track each background Task.Run in _backgroundTasks: ConcurrentDictionary<Task, byte> and drain it at the end of DisposeAsync (after the CTSs are cancelled). This makes server disposal deterministic — even if a test skips the wait, the server won't tear down while a background runner is still alive.

Testing

The test TaskTool_CancellationToken_GetTaskShowsWorkingBeforeCancel called
CancelTaskAsync and returned immediately without waiting for the background
Task.Run (the tool body) to finish. On Windows in Debug mode, thread-pool
scheduling pressure can keep that runner alive past server disposal, causing
McpServerImpl.DisposeAsync to race with it and—in the worst case—hang
waiting for the MRTR in-flight counter to reach zero.

Two fixes:

1. Test: add �wait _toolCancellationFired.Task.WaitAsync(...) after
   CancelTaskAsync, mirroring the pattern used by the sibling test
   TaskTool_CancellationToken_FiresWhenExplicitlyCancelled.

2. Infrastructure: track each background Task.Run in a
   ConcurrentDictionary<Task, byte> and drain it in DisposeAsync (after
   cancelling all CTSs).  This makes server disposal deterministic
   regardless of whether a test explicitly waits for tool cancellation.

Fixes: #1701

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@PranavSenthilnathan PranavSenthilnathan marked this pull request as draft July 14, 2026 01:21
@PranavSenthilnathan PranavSenthilnathan changed the title Fix flaky task cancellation test hang on Windows Debug CI (#1701) [WIP] Fix flaky task cancellation test hang on Windows Debug CI (#1701) Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flaky test host hang on Windows Debug CI: TaskCancellationIntegrationTests.TaskTool_CancellationToken_GetTaskShowsWorkingBeforeCancel

2 participants