fix(scripts): saturate the tsgo watchdog at Node's timer ceiling

An OPENCLAW_TSGO_TIMEOUT_MS above 2147483647 reached setTimeout unchanged,
where Node collapses it to a 1ms delay, so raising the override killed
healthy typechecks immediately instead of loosening the bound.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jesse Merhi
2026-08-15 14:20:12 +10:00
parent 3e5792477d
commit 6ba02c9d0a
2 changed files with 16 additions and 1 deletions
+6 -1
View File
@@ -18,6 +18,8 @@ import {
/** Watchdog bound for one tsgo run; sized well above a healthy whole-program check. */
const DEFAULT_TSGO_TIMEOUT_MS = 45 * 60 * 1000;
/** Node's timer ceiling: a longer delay silently becomes 1ms, so a raised override must saturate. */
const MAX_TSGO_TIMEOUT_MS = 2_147_483_647;
async function main(): Promise<void> {
const hostResources = {
@@ -49,7 +51,10 @@ async function main(): Promise<void> {
}
ensureRepoToolNodeModulesLink(tsgoPath);
const timeoutMs = readPositiveEnvInt("OPENCLAW_TSGO_TIMEOUT_MS", env, DEFAULT_TSGO_TIMEOUT_MS);
const timeoutMs = Math.min(
readPositiveEnvInt("OPENCLAW_TSGO_TIMEOUT_MS", env, DEFAULT_TSGO_TIMEOUT_MS),
MAX_TSGO_TIMEOUT_MS,
);
try {
// Managed run owns the whole tsgo process tree: on timeout it SIGKILLs the
// process group, because a wedged checker ignores SIGTERM and would otherwise
+10
View File
@@ -283,4 +283,14 @@ describe.skipIf(process.platform === "win32")("run-tsgo watchdog", () => {
expect(result.status).toBe(0);
expect(result.stderr).not.toContain("killed the tsgo process tree");
}, 30_000);
it("saturates an override past Node's timer ceiling instead of arming a 1ms watchdog", () => {
const cwd = createTempDir("openclaw-run-tsgo-watchdog-");
writeFakeTsgo(cwd, "#!/bin/sh\nsleep 1\nexit 0\n");
const result = runFakeTsgo(cwd, "2147483648");
expect(result.status).toBe(0);
expect(result.stderr).not.toContain("killed the tsgo process tree");
}, 30_000);
});