Skip to content

fix(dotnet): abort in-flight turns before disposing sessions on in-process shutdown - #1961

Closed
SteveSandersonMS wants to merge 1 commit into
mainfrom
stevesa/dotnet-win-inproc-ci
Closed

SteveSandersonMS wants to merge 1 commit into
mainfrom
stevesa/dotnet-win-inproc-ci

Conversation

@SteveSandersonMS

Copy link
Copy Markdown
Contributor

What

Cross-SDK parity with the Node.js in-process shutdown fix.

Over the in-process (FFI) transport the runtime shares the SDK process, so a turn still running when a session is disposed can leave that session's SQLite session.db handle open. Because there is no child process to terminate, the handle is never reclaimed — on Windows the file stays locked and the session-state temp directory can't be removed.

Changes

  • CopilotClient.StopAsync() now aborts any in-flight turn (session.AbortAsync()) before session.DisposeAsync(), releasing the handle. Aborting a session with no active turn is a no-op.
    • Scoped to InProcessRuntimeConnection only: stdio/tcp runtimes run in a child process we kill on shutdown (which frees the handle), and for external servers we don't own the runtime and aborting would cancel pending work other clients may still resume.
    • Abort + dispose run per-session in a single parallel Task.WhenAll.
    • Marked TEMPORARY — remove once the runtime cleans up fully on shutdown.
  • CI: re-enables the windows-latest + inprocess matrix leg in dotnet-sdk-tests.yml (previously excluded pending this fix).

Context

Follow-up to the equivalent Node.js SDK fix. See #1934 for the broader in-process transport tracking.

…ocess shutdown

Cross-SDK parity with the Node.js fix. Over the in-process (FFI) transport the
runtime shares the SDK process, so a turn still running when a session is
disposed can leave that session's SQLite session.db handle open. The handle is
not reclaimed by terminating a child process (there is none), so on Windows the
file stays locked and the session-state temp directory can't be removed.

StopAsync() now aborts any in-flight turn before DisposeAsync() for in-process
connections, releasing the handle. Scoped to InProcessRuntimeConnection only:
stdio/tcp runtimes run in a child process we kill on shutdown, and external
servers are shared. Abort+dispose run per-session in a single parallel
Task.WhenAll.

Re-enables the windows-latest + inprocess leg in dotnet-sdk-tests.yml.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@SteveSandersonMS

Copy link
Copy Markdown
Contributor Author

No, not sufficient.

@stephentoub
stephentoub deleted the stevesa/dotnet-win-inproc-ci branch August 7, 2026 16:04
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.

1 participant