fix(test-runner): cancellation terminates the run; win32 kills the whole tree

Installing SIGINT/SIGTERM forwarders suppresses Node's default
terminate-on-signal, so a cancelled run killed the current child and
kept LAUNCHING shards — observed as paid runs continuing to burn API
spend after Ctrl-C (codex adversarial, repro'd ALIVE_AFTER_SIGTERM).
The first signal now also schedules the parent's own exit after the
children's SIGKILL grace, and both shard pools consult
isTerminationRequested() before taking new work. On win32,
killProcessGroup uses taskkill /T /F — detached:true creates no
killable group there, and a bare child.kill orphaned every grandchild
(ports, locks, and the inherited pipes that kept close from firing).
Also: the tree-mutating serial shard prints dirty generated artifacts
when it dies mid-regeneration, and --shard CI-matrix mode gets the
same size-scaled wall deadline as full-suite mode.
This commit is contained in:
Garry Tan
2026-08-15 17:01:40 -07:00
parent 84a93766f2
commit 9e72b4ac7f
4 changed files with 155 additions and 3 deletions
+5
View File
@@ -59,6 +59,7 @@ import {
exactTestFileSelectors,
forwardAndClassify,
installChildSignalForwarding,
isTerminationRequested,
killProcessGroup,
strictTestExitCode,
} from './test-strict-output';
@@ -517,6 +518,10 @@ export async function runPaidShards(
let next = 0;
const worker = async (): Promise<void> => {
while (true) {
// Cancellation (SIGINT/SIGTERM) must stop the RUN: the signal
// forwarders kill in-flight children, and this guard stops the pool
// from launching replacement shards that would keep burning API spend.
if (isTerminationRequested()) return;
const index = next;
next += 1;
if (index >= shards.length) return;