Skip to content

fix: wait for graceful subprocess shutdown before SIGTERM - #642

Merged
qing-ant merged 2 commits into
anthropics:mainfrom
Bortlesboat:fix/graceful-shutdown-625
Mar 19, 2026
Merged

qing-ant merged 2 commits into
anthropics:mainfrom
Bortlesboat:fix/graceful-shutdown-625

Conversation

@Bortlesboat

Copy link
Copy Markdown
Contributor

Summary

  • After closing stdin, wait up to 5 seconds for the CLI process to exit gracefully before sending SIGTERM
  • Previously terminate() was called immediately after stdin EOF, which could interrupt session file writes and lose the last assistant message
  • Updated test to verify that terminate is not called when the process exits gracefully

Fixes #625

Bortlesboat and others added 2 commits March 6, 2026 13:05
After closing stdin, give the CLI process up to 5 seconds to flush its
session file before sending SIGTERM. Previously, terminate() was called
immediately after stdin EOF, which could interrupt the session file write
and cause the last assistant message to be lost.

Fixes anthropics#625

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…aths

Add two tests for the close() grace period behavior:
- test_close_terminates_after_grace_period_timeout: verifies SIGTERM is
  sent when the subprocess doesn't exit within the grace period
- test_close_skips_wait_when_already_exited: verifies no terminate call
  when process has already exited (returncode != None)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Bortlesboat

Copy link
Copy Markdown
Contributor Author

Quick follow-up from my side: I’m treating review-required PRs as top priority this week. If you want any specific changes, rebase, or split, I can turn them around quickly.

@codecov-commenter

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

@qing-ant

Copy link
Copy Markdown
Contributor

LGTM — thanks for tracking this down.

Verified e2e: on main, terminate() fires every single time (returncode is always still None when close() runs), so the race is live on every call — we just get lucky on fast disks. With this patch it's 0/3, CLI exits on its own in ~500ms. The 5s window never actually blocks.

One tiny thing: the timeout test patches anyio.fail_after to raise on construction rather than actually timing out. Works fine, just a shortcut — not worth holding on.

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.

Session file not flushed before subprocess termination in ClaudeSDKClient

3 participants