Fix .NET client startup cleanup race#1206
Conversation
Clean up partially established CLI connections if startup fails during protocol negotiation, and avoid rethrowing failed startup tasks during force-stop cleanup. Add a TCP fake-CLI regression test that drops during startup verification and verifies ForceStopAsync remains cleanup-safe. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Pull request overview
This PR fixes a cleanup race in the .NET SDK’s client startup path where a dropped TCP CLI connection during protocol negotiation could cause subsequent cleanup (ForceStopAsync / dispose) to rethrow the original startup failure instead of just releasing resources.
Changes:
- Ensures partially-established connections are torn down if startup verification/configuration fails (protocol negotiation + session FS config).
- Adjusts force-stop/stop cleanup to treat an already-failed startup task as “cleanup complete” (avoids rethrowing startup failures during teardown).
- Adds an E2E regression test using a fake TCP CLI that drops the connection during startup verification to validate
ForceStopAsyncsafety afterward.
Show a summary per file
| File | Description |
|---|---|
| dotnet/src/Client.cs | Adds startup failure cleanup for partially established connections; makes teardown ignore faulted startup tasks and improves cleanup error reporting/logging. |
| dotnet/test/E2E/ClientOptionsE2ETests.cs | Adds an E2E regression test with a fake TCP CLI that drops during startup to ensure ForceStopAsync does not rethrow. |
Copilot's findings
- Files reviewed: 2/2 changed files
- Comments generated: 1
Ensure child CLI processes are terminated when startup fails before a Connection is produced, including TCP connect failures after the CLI announces a port. Add a regression test that verifies a fake TCP CLI process is killed when the announced port cannot be connected to. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Cross-SDK Consistency Review ✅This PR is a .NET-only internal bug fix and maintains full cross-SDK consistency. No changes are needed in Node.js, Python, or Go. What this PR fixes: A race in the .NET client's startup cleanup — if a TCP CLI connection drops after being established but before protocol verification completes, the stored Why no other SDK is affected:
The
|
A four-way parallel run of the .NET SDK E2E suite exposed a load-sensitive cleanup race: if the TCP CLI connection drops after a connection is created but before startup finishes protocol negotiation, later force-stop/dispose cleanup can rethrow the failed startup task instead of just releasing resources.
This change makes startup cleanup tear down partially established connections before rethrowing the startup failure, and makes force-stop cleanup treat an already-failed startup task as cleanup-complete. It also adds a fake TCP CLI regression test that announces a port, accepts the initial JSON-RPC connection, and drops during startup verification to ensure
ForceStopAsyncremains safe afterward.Validation:
dotnet test dotnet\test\GitHub.Copilot.SDK.Test.csproj --filter FullyQualifiedName~ForceStop_Does_Not_Rethrow_When_Tcp_Cli_Drops_During_Startup