Skip to content

Commit 1d84a95

Browse files
committed
fix(tests): keep self-exited stall runs unretried with code intact
A stall-declared run that exits on its own is never a stall: SIGTERM death reads as null or 143, any other code is the child's own and must survive unretried.
1 parent f19f001 commit 1d84a95

2 files changed

Lines changed: 26 additions & 3 deletions

File tree

scripts/test-parallel.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,26 @@ describe("runWithWatchdog", () => {
9292
expect(stalls).toEqual([[1, 3]]);
9393
});
9494

95+
test("a stall-declared run that exits on its own keeps its code and is not retried", async () => {
96+
// Ignores SIGTERM so the watchdog's stall kill cannot take it out, then
97+
// exits 3 on its own well after the stall window (so the stall is
98+
// declared first). The real code must survive and the run must not retry.
99+
const result = await runWithWatchdog({
100+
command: process.execPath,
101+
args: [
102+
"-e",
103+
'process.on("SIGTERM", () => {}); setTimeout(() => process.exit(3), 4_000);',
104+
],
105+
stallMs: TEST_STALL_MS,
106+
onStall: () => {
107+
throw new Error("must not retry a run that exited on its own");
108+
},
109+
});
110+
expect(result.exitCode).toBe(3);
111+
expect(result.stalled).toBe(false);
112+
expect(result.attempts).toBe(1);
113+
});
114+
95115
test("gives up after the final attempt with exit code 1", async () => {
96116
const stalls: [number, number][] = [];
97117
const result = await runWithWatchdog({

scripts/test-parallel.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,12 @@ async function runAttempt(
126126
exited = true;
127127
clearInterval(watchdog);
128128
await Promise.allSettled(pumps);
129-
// null means killed by a signal; the stalled flag says who did it.
130-
const exitCode = raw === null ? (stalled ? STALL_CODE : 1) : raw;
131-
return { exitCode, stalled };
129+
// A SIGTERM kill surfaces as null (died by signal) or 143 (Bun's SIGTERM
130+
// exit); any other code means the child exited on its own and keeps its
131+
// code unretried, even if the watchdog already fired.
132+
const killedByWatchdog = stalled && (raw === null || raw === 143);
133+
const exitCode = killedByWatchdog ? STALL_CODE : (raw ?? 1);
134+
return { exitCode, stalled: killedByWatchdog };
132135
}
133136

134137
export async function runWithWatchdog(

0 commit comments

Comments
 (0)