fix: closing a terminal on Windows never kills its processes#3063
fix: closing a terminal on Windows never kills its processes#3063badcuban wants to merge 1 commit into
Conversation
node-pty's WindowsTerminal.kill(signal) throws 'Signals not supported on windows.' whenever a signal is passed. The terminal manager's kill escalation always passes SIGTERM (then SIGKILL), so on win32 both attempts fail silently and the shell plus everything it spawned (dev servers, watchers) keeps running detached until the app exits, while the session and its history are deleted. On win32, call kill() with no signal instead and skip the escalation: node-pty's signal-less Windows kill terminates every process attached to the pty's console. POSIX behavior is unchanged. The two existing escalation tests ran against the host platform and would exercise the win32 path on Windows machines, so they now pin platform: 'linux'; a new test pins win32 and asserts a single signal-less kill. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Approved This is a well-scoped platform-specific bug fix for Windows terminal process handling, with clear documentation explaining the node-pty limitation and appropriate test coverage added. You can customize Macroscope's approvability policy. Learn more. |
What changed
On Windows, closing a terminal (trash can, or closing its thread) never kills the terminal's processes.
runKillEscalationinapps/server/src/terminal/Layers/Manager.tsalways passes a signal toPtyProcess.kill(SIGTERM, then SIGKILL after the grace period), and node-pty'sWindowsTerminal.kill(signal)throws'Signals not supported on windows.'whenever a signal is provided. Both attempts are caught and logged asfailed to kill terminal process, and nothing is killed.The result on win32: the shell and everything started in it (dev servers, watchers) keep running detached until the whole app exits, still holding their ports. Since closing also removes the session and deletes its history, the orphans are invisible afterwards; reopening spawns a fresh pty next to the still-running old one.
Repro (Windows): open a thread terminal, run anything that binds a port (
npm run dev), close the terminal from the UI, then check the process list or the port. The dev server is still running.The fix
On
win32, callkill()with no signal and skip the SIGTERM/SIGKILL escalation. node-pty's signal-less Windows kill enumerates the console process list and terminates every process attached to the pty's console; that code path exists in node-pty precisely so node servers don't outlive the terminal (its source references microsoft/vscode#26807). POSIX behavior is unchanged.TerminalProcessSignalError.signalbecomes optional because the Windows failure case has no signal to report.Tests
kills the terminal without a signal on Windows(manager pinned toplatform: "win32", asserts exactly one signal-less kill).platform: "linux"and deterministically test the POSIX escalation everywhere.vp check(0 errors),vp run typecheck, and the terminal Manager suite (43 passed) all pass.Found and verified in a downstream fork running on Windows 11; the diff here is built against current
main.🤖 Generated with Claude Code
Note
Medium Risk
Changes process teardown on Windows for all terminal close and shutdown paths; incorrect behavior could leave orphans or kill too aggressively, but scope is isolated to
runKillEscalationwith POSIX unchanged.Overview
Fixes terminal close on Windows leaving shell and child processes (e.g. dev servers) running because node-pty rejects signaled kills.
runKillEscalationinManager.tsnow branches onwin32: it callsprocess.kill()with no signal and skips the SIGTERM → grace → SIGKILL path. POSIX behavior is unchanged.TerminalProcessSignalError.signalis optional so Windows failures without a signal still type-check.Tests add
kills the terminal without a signal on Windowsand pinplatform: "linux"on the existing escalation/shutdown tests so POSIX escalation is asserted on every host.Reviewed by Cursor Bugbot for commit 3a9b11e. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Fix terminal close on Windows to kill processes without a signal
On Windows,
process.kill()requires no signal argument to correctly terminate a console process tree. TherunKillEscalationutil in Manager.ts now branches on platform: onwin32it callskill()without a signal and skips the SIGTERM/SIGKILL escalation sequence; on other platforms, behavior is unchanged. Thesignalfield onTerminalProcessSignalErroris made optional to accommodate the signal-less kill path.Macroscope summarized 3a9b11e.