Skip to content

Commit 4f7d1f4

Browse files
committed
fix(scripts): clamp boundary artifact timers
1 parent c310f8c commit 4f7d1f4

2 files changed

Lines changed: 23 additions & 2 deletions

File tree

scripts/prepare-extension-package-boundary-artifacts.mjs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const ROOT_SHIMS_MAX_OLD_SPACE_SIZE =
1818
const ROOT_SHIMS_NODE_OPTIONS =
1919
`${process.env.NODE_OPTIONS ?? ""} --max-old-space-size=${ROOT_SHIMS_MAX_OLD_SPACE_SIZE}`.trim();
2020
const NODE_STEP_ABORT_KILL_GRACE_MS = 1_000;
21+
const MAX_TIMER_TIMEOUT_MS = 2_147_000_000;
2122
const NODE_STEP_PARENT_SIGNALS = ["SIGHUP", "SIGINT", "SIGTERM"];
2223
const NODE_STEP_PARENT_SIGNAL_EXIT_CODES = new Map([
2324
["SIGHUP", 129],
@@ -469,10 +470,19 @@ function installNodeStepParentSignalForwarders() {
469470
});
470471
}
471472

473+
function resolveNodeStepTimerTimeoutMs(valueMs) {
474+
const value = Number(valueMs);
475+
if (!Number.isFinite(value)) {
476+
return MAX_TIMER_TIMEOUT_MS;
477+
}
478+
return Math.min(Math.max(Math.floor(value), 1), MAX_TIMER_TIMEOUT_MS);
479+
}
480+
472481
/**
473482
* Runs one artifact step with timeout, abort propagation, and prefixed output.
474483
*/
475484
export function runNodeStep(label, args, timeoutMs, params = {}) {
485+
const resolvedTimeoutMs = resolveNodeStepTimerTimeoutMs(timeoutMs);
476486
const abortController = params.abortController;
477487
const spawnImpl = params.spawnImpl ?? spawn;
478488
installNodeStepParentSignalForwarders();
@@ -555,8 +565,8 @@ export function runNodeStep(label, args, timeoutMs, params = {}) {
555565
stdoutWriter.flush();
556566
stderrWriter.flush();
557567
abortSiblingSteps(abortController);
558-
rejectPromise(new Error(`${label} timed out after ${timeoutMs}ms`));
559-
}, timeoutMs);
568+
rejectPromise(new Error(`${label} timed out after ${resolvedTimeoutMs}ms`));
569+
}, resolvedTimeoutMs);
560570
abortController?.signal.addEventListener("abort", abortStep, { once: true });
561571

562572
child.stdout.setEncoding("utf8");

test/scripts/prepare-extension-package-boundary-artifacts.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import os from "node:os";
77
import path from "node:path";
88
import { setTimeout as delay } from "node:timers/promises";
99
import { pathToFileURL } from "node:url";
10+
import { MAX_TIMER_TIMEOUT_MS } from "@openclaw/normalization-core/number-coercion";
1011
import { afterEach, describe, expect, it, vi } from "vitest";
1112
import { resolveWindowsTaskkillPath } from "../../scripts/lib/windows-taskkill.mjs";
1213
import {
@@ -317,6 +318,16 @@ describe("prepare-extension-package-boundary-artifacts", () => {
317318
expect(signals).toEqual(["SIGKILL"]);
318319
});
319320

321+
it("clamps oversized prep step timers before scheduling", async () => {
322+
await expect(
323+
runNodeStep(
324+
"slow-success",
325+
["--eval", "setTimeout(() => process.exit(0), 25);"],
326+
MAX_TIMER_TIMEOUT_MS + 1,
327+
),
328+
).resolves.toBeUndefined();
329+
});
330+
320331
it.runIf(process.platform !== "win32")("kills timed-out prep step process groups", async () => {
321332
const rootDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-boundary-timeout-group-"));
322333
tempRoots.add(rootDir);

0 commit comments

Comments
 (0)