mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix(scripts): clamp boundary check timers
This commit is contained in:
@@ -37,6 +37,7 @@ const FAILURE_OUTPUT_TAIL_LINES = 40;
|
||||
const STEP_OUTPUT_MAX_CHARS = 256 * 1024;
|
||||
const STEP_PROCESS_GROUP_EXIT_POLL_MS = 25;
|
||||
const STEP_POST_FORCE_KILL_WAIT_MS = 1_000;
|
||||
const MAX_TIMER_TIMEOUT_MS = 2_147_000_000;
|
||||
const SLOW_COMPILE_SUMMARY_LIMIT = 10;
|
||||
const COMPILE_INPUT_EXTENSIONS = new Set([".ts", ".tsx", ".mts", ".cts", ".js", ".mjs", ".json"]);
|
||||
const ROOTDIR_BOUNDARY_CANARY_IMPORT_PATH =
|
||||
@@ -337,13 +338,22 @@ function writeStampFile(filePath) {
|
||||
writeFileSync(filePath, `${new Date().toISOString()}\n`, "utf8");
|
||||
}
|
||||
|
||||
function resolveStepTimerTimeoutMs(valueMs) {
|
||||
const value = Number(valueMs);
|
||||
if (!Number.isFinite(value)) {
|
||||
return MAX_TIMER_TIMEOUT_MS;
|
||||
}
|
||||
return Math.min(Math.max(Math.floor(value), 1), MAX_TIMER_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
function runNodeStep(label, args, timeoutMs) {
|
||||
const resolvedTimeoutMs = resolveStepTimerTimeoutMs(timeoutMs);
|
||||
const startedAt = Date.now();
|
||||
const result = spawnSync(process.execPath, args, {
|
||||
cwd: repoRoot,
|
||||
encoding: "utf8",
|
||||
maxBuffer: 16 * 1024 * 1024,
|
||||
timeout: timeoutMs,
|
||||
timeout: resolvedTimeoutMs,
|
||||
});
|
||||
|
||||
if (result.status === 0 && !result.error) {
|
||||
@@ -352,7 +362,7 @@ function runNodeStep(label, args, timeoutMs) {
|
||||
|
||||
const timeoutSuffix =
|
||||
result.error?.name === "Error" && result.error.message.includes("ETIMEDOUT")
|
||||
? `${label} timed out after ${timeoutMs}ms`
|
||||
? `${label} timed out after ${resolvedTimeoutMs}ms`
|
||||
: "";
|
||||
const errorSuffix = result.error ? result.error.message : "";
|
||||
const note = [timeoutSuffix, errorSuffix].filter(Boolean).join("\n");
|
||||
@@ -391,6 +401,7 @@ function abortSiblingSteps(abortController) {
|
||||
* Runs one node-based boundary check step with timeout and output capture.
|
||||
*/
|
||||
export function runNodeStepAsync(label, args, timeoutMs, params = {}) {
|
||||
const resolvedTimeoutMs = resolveStepTimerTimeoutMs(timeoutMs);
|
||||
const abortController = params.abortController;
|
||||
const killProcess = params.killProcess ?? process.kill.bind(process);
|
||||
const onFailure = params.onFailure;
|
||||
@@ -499,7 +510,7 @@ export function runNodeStepAsync(label, args, timeoutMs, params = {}) {
|
||||
stderr: stderrText,
|
||||
kind: "timeout",
|
||||
elapsedMs: Date.now() - startedAt,
|
||||
note: `${label} timed out after ${timeoutMs}ms`,
|
||||
note: `${label} timed out after ${resolvedTimeoutMs}ms`,
|
||||
}),
|
||||
),
|
||||
label,
|
||||
@@ -508,14 +519,14 @@ export function runNodeStepAsync(label, args, timeoutMs, params = {}) {
|
||||
stderr: stderrText,
|
||||
kind: "timeout",
|
||||
elapsedMs: Date.now() - startedAt,
|
||||
note: `${label} timed out after ${timeoutMs}ms`,
|
||||
note: `${label} timed out after ${resolvedTimeoutMs}ms`,
|
||||
},
|
||||
);
|
||||
onFailure?.(error);
|
||||
abortSiblingSteps(abortController);
|
||||
rejectPromise(toLintErrorObject(error, "Step timed out"));
|
||||
})();
|
||||
}, timeoutMs);
|
||||
}, resolvedTimeoutMs);
|
||||
|
||||
child.stdout.setEncoding("utf8");
|
||||
child.stderr.setEncoding("utf8");
|
||||
|
||||
@@ -5,6 +5,7 @@ import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { pathToFileURL } from "node:url";
|
||||
import { MAX_TIMER_TIMEOUT_MS } from "@openclaw/normalization-core/number-coercion";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import {
|
||||
acquireBoundaryCheckLock,
|
||||
@@ -432,6 +433,19 @@ describe("check-extension-package-tsc-boundary", () => {
|
||||
expect(elapsedMs).toBeGreaterThanOrEqual(0);
|
||||
}, 30_000);
|
||||
|
||||
it("clamps oversized async node step timers before scheduling", async () => {
|
||||
await expect(
|
||||
runNodeStepAsync(
|
||||
"slow-success",
|
||||
["--eval", "setTimeout(() => process.exit(0), 25);"],
|
||||
MAX_TIMER_TIMEOUT_MS + 1,
|
||||
),
|
||||
).resolves.toMatchObject({
|
||||
stderr: "",
|
||||
stdout: "",
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps async node step failure output bounded", async () => {
|
||||
const child = new EventEmitter() as EventEmitter & {
|
||||
kill: (signal?: NodeJS.Signals | number) => boolean;
|
||||
|
||||
Reference in New Issue
Block a user