Repository navigation
fix: stop every process a run started on Windows, whatever its parents - #492
Merged
Merged
Conversation
On Windows CI, MSYS's bash runs npm's script through a fork that exits, which breaks the parent chain taskkill /T follows, so a stopped or timed-out check left npm and its processes running (#490). Under Bun each process runProcess starts goes into a Windows Job Object, which what it starts joins however its parents come and go, and a stop or time limit terminates the job. Under Node and elsewhere the tree is stopped as before. A test reproduces the case on any machine with a shell that starts a process in the background and exits.
This was referenced Oct 18, 2026
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.
Closes #490 (closed by hand on merge).
Cause (from a diagnostic on Windows CI, draft #491)
On CI, npm is a bash script, and MSYS's bash runs it through a fork that exits, leaving npm and everything below it with a parent that no longer exists:
taskkill /T, whichrunProcessused to stop a tree, follows parents, so a stop or a time limit ended the bash processes and left npm, the check and what it started running. On the owner's machine npm runs throughshwith no such fork, so it never showed there.Change (
src/process.ts)runProcessstarts goes into a Windows Job Object as it starts; what it starts joins the job however its parents come and go. A run a stop or its time limit ended terminates the job (TerminateJobObject), throughkernel32withbun:ffi, as the session lock already does.taskkill /T, the process group).bun:ffiis imported by a name Node never resolves, so the verification layer still loads under Node.runProcessskipped.Checks
packages/core/tests/process-tree.test.tsreproduces On Windows, stopping a check can leave its processes running #490 on any machine: a process starts a shell (cmd /c start /borsh -c "… &"), which starts the last process in the background and exits, so the last one has no living parent; the test checks it is alive then, stops the run, and checks it is gone. It fails ondev'sprocess.tson Windows (the process survives) and passes with the job. The shell is not a Node process because Bun and Node end their own children when they exit, which hid the case in a first version of the test.gate.test.ts's check that a stopped check's processes are gone now runs on Windows too, as On Windows, stopping a check can leave its processes running #490's acceptance asks.bun run checklocally (Windows): exit 0; root 264 passed; engine 331 passed, 3 skipped; budgets within limits.Risk, to watch in CI: the process is put in its job just after it starts, so a process it started in that instant would escape; Node cannot start one suspended. The gate test on Windows CI is the check.