@kontextmind/kxm
Version:
KXM local-first multi-agent orchestration and operator dashboard
54 lines (44 loc) • 1.42 kB
JavaScript
// Wall-clock guard for a test suite. Node's --test-timeout also bounds each
// file (each file is a test), so the suite scripts do not pass it. This
// bounds the process that runs them.
import { spawn } from "node:child_process";
const timeoutMs = Number(process.argv[2]);
const command = process.argv[3];
const args = process.argv.slice(4);
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0 || command === undefined) {
console.error("usage: run-bounded.mjs <timeout-ms> <command> [args...]");
process.exit(2);
}
const child = spawn(command, args, { stdio: "inherit", detached: true });
let timedOut = false;
function signalGroup(signal) {
if (child.pid === undefined) return;
try {
process.kill(-child.pid, signal);
} catch {
try { child.kill(signal); } catch { /* already gone */ }
}
}
const timer = setTimeout(() => {
timedOut = true;
console.error(`wall clock ${timeoutMs}ms exceeded`);
signalGroup("SIGTERM");
setTimeout(() => signalGroup("SIGKILL"), 2000).unref();
}, timeoutMs);
for (const signal of ["SIGINT", "SIGTERM"]) {
process.on(signal, () => {
signalGroup(signal);
});
}
child.on("error", (error) => {
clearTimeout(timer);
console.error(error.message);
process.exit(1);
});
child.on("exit", (code, signal) => {
clearTimeout(timer);
if (timedOut) process.exit(124);
if (signal) process.exit(1);
process.exit(code ?? 1);
});