mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 12:56:01 -06:00
fix(scripts): set the tsgo watchdog default from measured lane duration
ClawSweeper on c7a699ee82 reversed its earlier guidance: the opt-in default
adopted last iteration "deliberately preserves the indefinite tsgo hang that
this PR is meant to fix". Its objection was never that a default existed, only
that 45 minutes was unmeasured.
Measured instead of guessed: hosted tsgo lanes (check-test-types, and its core
stripes) complete in 1-2 minutes across recent successful main runs, against CI
job caps of 15-20 minutes. 30 minutes is 15-30x the observed duration, leaves
room for a far slower local host, and still bounds the 90-minute and multi-hour
wedges that motivated this PR. OPENCLAW_TSGO_TIMEOUT_MS remains the documented
override for hosts that need longer.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -694,11 +694,12 @@ Native dependency policy:
|
|||||||
after 5 minutes with no stdout or stderr output. Set
|
after 5 minutes with no stdout or stderr output. Set
|
||||||
`OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS=0` to disable the watchdog for
|
`OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS=0` to disable the watchdog for
|
||||||
an intentionally silent investigation.
|
an intentionally silent investigation.
|
||||||
- `scripts/run-tsgo.mjs` waits indefinitely by default. Set
|
- `scripts/run-tsgo.mjs` terminates a tsgo run after 30 minutes, so a
|
||||||
`OPENCLAW_TSGO_TIMEOUT_MS` to bound a run on hosts where a wedged
|
wedged compiler fails loudly instead of blocking its caller forever.
|
||||||
compiler would otherwise block its caller forever; on expiry the whole
|
Hosted tsgo lanes finish in 1-2 minutes; raise
|
||||||
tsgo process tree is killed and the run fails. Values above Node's
|
`OPENCLAW_TSGO_TIMEOUT_MS` on a slower host. On expiry the whole tsgo
|
||||||
timer ceiling saturate instead of collapsing to a 1ms deadline.
|
process tree is killed and the run fails. Values above Node's timer
|
||||||
|
ceiling saturate instead of collapsing to a 1ms deadline.
|
||||||
|
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
|
||||||
|
|||||||
+10
-8
@@ -16,6 +16,12 @@ import {
|
|||||||
shouldSkipSparseTsgoGuardError,
|
shouldSkipSparseTsgoGuardError,
|
||||||
} from "./lib/tsgo-sparse-guard.mts";
|
} from "./lib/tsgo-sparse-guard.mts";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hosted tsgo lanes finish in 1-2 minutes and their CI jobs cap at 15-20, so 30
|
||||||
|
* leaves headroom for a far slower local host while still bounding a wedge that
|
||||||
|
* would otherwise never report. Raise OPENCLAW_TSGO_TIMEOUT_MS for slower hosts.
|
||||||
|
*/
|
||||||
|
const DEFAULT_TSGO_TIMEOUT_MS = 30 * 60 * 1000;
|
||||||
/** Node's timer ceiling: a longer delay silently becomes 1ms, so a raised override must saturate. */
|
/** 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;
|
const MAX_TSGO_TIMEOUT_MS = 2_147_483_647;
|
||||||
|
|
||||||
@@ -49,14 +55,10 @@ async function main(): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ensureRepoToolNodeModulesLink(tsgoPath);
|
ensureRepoToolNodeModulesLink(tsgoPath);
|
||||||
// Opt-in deadline: no supported duration contract covers every host and project,
|
const timeoutMs = Math.min(
|
||||||
// so an unset value keeps the pre-existing unbounded wait rather than guessing one.
|
readPositiveEnvInt("OPENCLAW_TSGO_TIMEOUT_MS", env, DEFAULT_TSGO_TIMEOUT_MS),
|
||||||
const timeoutMs = env.OPENCLAW_TSGO_TIMEOUT_MS?.trim()
|
MAX_TSGO_TIMEOUT_MS,
|
||||||
? Math.min(
|
);
|
||||||
readPositiveEnvInt("OPENCLAW_TSGO_TIMEOUT_MS", env, MAX_TSGO_TIMEOUT_MS),
|
|
||||||
MAX_TSGO_TIMEOUT_MS,
|
|
||||||
)
|
|
||||||
: undefined;
|
|
||||||
try {
|
try {
|
||||||
// Managed run owns the whole tsgo process tree: on timeout it SIGKILLs the
|
// Managed run owns the whole tsgo process tree: on timeout it SIGKILLs the
|
||||||
// process group, because a wedged checker ignores SIGTERM and would otherwise
|
// process group, because a wedged checker ignores SIGTERM and would otherwise
|
||||||
|
|||||||
@@ -277,7 +277,7 @@ describe.skipIf(process.platform === "win32")("run-tsgo watchdog", () => {
|
|||||||
expect(result.stderr.trim().split("\n").at(-1)).toBe("[tsgo] FAILED (exit 1)");
|
expect(result.stderr.trim().split("\n").at(-1)).toBe("[tsgo] FAILED (exit 1)");
|
||||||
}, 30_000);
|
}, 30_000);
|
||||||
|
|
||||||
it("arms no watchdog until an operator opts in", () => {
|
it("leaves a healthy run alone under the default deadline", () => {
|
||||||
const cwd = createTempDir("openclaw-run-tsgo-watchdog-");
|
const cwd = createTempDir("openclaw-run-tsgo-watchdog-");
|
||||||
writeFakeTsgo(cwd, "#!/bin/sh\nsleep 2\nexit 0\n");
|
writeFakeTsgo(cwd, "#!/bin/sh\nsleep 2\nexit 0\n");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user