stopWhenThisEnds
uses node:child_process
Stop a process this one started once this one ends, however it ends: killed (SIGKILL, a hung test's time limit),
it can't stop anything itself, and what it started would run on for good, orphaned. A watchdog process (one for
this process, started with the first it's told of: WATCHDOG) is told each process kept and each that ends; this
process's end closes the pipe to it, and it stops those still running: asked to (SIGTERM), then made to (SIGKILL)
if one hasn't in 5 seconds. (Something kept that isn't a child process, a server in this one, is withChildren's.)
import { WATCHDOG, watchdogs } from "#codebase/tcmts/cli/test/e2e/harness"; import { spawn } from "node:child_process"; import type { ChildProcess } from "node:child_process"; export function stopWhenThisEnds(c: ChildProcess): void { if (typeof c.once !== "function" || !c.pid) return; let w = watchdogs.get(process.pid); if (!w) { // (its own process group, so it outlives a stop of this one's; nothing of this one's environment: it isn't a // tcm, and runs no code of the codebase) w = spawn(process.execPath, ["-e", WATCHDOG], { stdio: ["pipe", "ignore", "ignore"], detached: true, env: { PATH: process.env.PATH ?? "" }, }); // (it doesn't keep this process alive, nor fail it if it goes) w.unref(); w.stdin!.on("error", () => {}); (w.stdin as unknown as { unref(): void }).unref(); watchdogs.set(process.pid, w); } const pipe = w.stdin!; pipe.write(`+${c.pid}\n`); // (so a pid used again later, by something else, isn't stopped) c.once("exit", () => pipe.write(`-${c.pid}\n`)); }