Actually kill the Claude process tree on stop#208
Open
leonidasbarkas98-cpu wants to merge 1 commit into
Open
Conversation
Clicking Stop showed 'Claude code was stopped.' (plus a misleading red 'Error running Claude: The operation was aborted' box) but the work kept running until VS Code was closed (andrepimenta#178, andrepimenta#115). Root cause is the kill ordering in _killClaudeProcess. abort() ran first: on Windows the tracked PID is the cmd.exe shell from spawn(..., shell: true), so abort() synchronously killed only that shell and set child.killed. The taskkill /pid X /t /f that followed — the correct tree kill — hit an already-dead root, could not enumerate the process tree anymore and failed silently (errors are swallowed), so the real claude worker (a grandchild) and everything it spawned orphaned and kept running. The pre-set killed flag also turned the exit-wait/SIGKILL escalation into dead code, and the synchronous AbortError surfaced as the red error box. Fix: invert the order. 1. Clear _currentClaudeProcess first (before any await) so close/error events firing mid-kill hit the handlers' no-current-process guards and no-op — no false error box. 2. Tree-kill (SIGTERM) while the root is still alive, wait up to 2s for the exit — 'exitCode !== null' also covers a death Node observed during the wait, since taskkill never sets killed — then escalate to SIGKILL only if the process is really still running. 3. abort() last, purely as cleanup of the AbortController; its late AbortError is dropped by the error handler's guard. All kill paths benefit: the Stop button, New Chat and panel disposal. Unix/WSL branches of _killProcessGroup are untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Clicking Stop showed "Claude code was stopped." (plus a misleading red "Error running Claude: The operation was aborted" box) but the work kept running until VS Code was closed.
Root cause is the kill ordering in
_killClaudeProcess.abort()ran first: on Windows the tracked PID is the cmd.exe shell fromspawn(..., shell: true), so abort() synchronously killed only that shell and setchild.killed. Thetaskkill /pid X /t /fthat followed — the correct tree kill — hit an already-dead root, could not enumerate the process tree anymore and failed silently, so the real claude worker (a grandchild) and everything it spawned orphaned and kept running. The pre-setkilledflag also turned the exit-wait/SIGKILL escalation into dead code, and the synchronous AbortError surfaced as the red error box.The fix inverts the order: clear
_currentClaudeProcessfirst (late close/error events hit the handlers' guards and no-op — no false error box), tree-kill while the root is still alive with a 2s exit-wait and SIGKILL escalation (exitCode !== nullalso covers a death observed during the wait, since taskkill never setskilled), andabort()last as pure cleanup.All kill paths benefit: the Stop button, New Chat and panel disposal. Unix/WSL branches are untouched.
Addresses #178 and #115. Complementary to #197 (which cancels pending permission requests on stop); the two apply independently.
Based on current main (ab6e307),
tsc --noEmitclean, no new dependencies.