






















@@ -46,6 +46,7 @@ export const LOG_TAIL_MAX_BYTES = 1024 * 1024;
4646const SHELL_TIMEOUT_KILL_GRACE_MS = 10_000;
4747const SHELL_POST_FORCE_KILL_WAIT_MS = 1_000;
4848const SHELL_PROCESS_GROUP_EXIT_POLL_MS = 25;
49+const MAX_TIMER_TIMEOUT_MS = 2_147_000_000;
4950const DEFAULT_TIMINGS_FILE = path.join(ROOT_DIR, ".artifacts/docker-tests/lane-timings.json");
5051const DEFAULT_GITHUB_WORKFLOW = "openclaw-live-and-e2e-checks-reusable.yml";
5152const IS_MAIN = process.argv[1]
@@ -135,6 +136,24 @@ function parseBool(raw, fallback) {
135136return !/^(?:0|false|no)$/i.test(raw);
136137}
137138139+function numericTimerValueMs(valueMs) {
140+const value = Number(valueMs);
141+return Number.isFinite(value) ? Math.floor(value) : undefined;
142+}
143+144+function resolveTimerTimeoutMs(valueMs, fallbackMs = MAX_TIMER_TIMEOUT_MS) {
145+const value = numericTimerValueMs(valueMs) ?? numericTimerValueMs(fallbackMs);
146+return Math.min(Math.max(value ?? MAX_TIMER_TIMEOUT_MS, 1), MAX_TIMER_TIMEOUT_MS);
147+}
148+149+function resolveOptionalTimerTimeoutMs(valueMs) {
150+const value = numericTimerValueMs(valueMs);
151+if (value === undefined || value <= 0) {
152+return undefined;
153+}
154+return resolveTimerTimeoutMs(value);
155+}
156+138157function resourceLimitsSummary(resourceLimits) {
139158return Object.entries(resourceLimits)
140159.map(([resource, limit]) => `${resource}=${String(limit)}`)
@@ -567,7 +586,13 @@ export function runShellCommand({
567586return activeChildrenShutdownPromise.then(() => shellCommandSkippedForShutdown());
568587}
569588return new Promise((resolve) => {
570-const pipeOutput = Boolean(logFile || noOutputTimeoutMs > 0);
589+const resolvedTimeoutMs = resolveOptionalTimerTimeoutMs(timeoutMs);
590+const resolvedNoOutputTimeoutMs = resolveOptionalTimerTimeoutMs(noOutputTimeoutMs);
591+const resolvedTimeoutKillGraceMs = resolveTimerTimeoutMs(
592+timeoutKillGraceMs,
593+SHELL_TIMEOUT_KILL_GRACE_MS,
594+);
595+const pipeOutput = Boolean(logFile || resolvedNoOutputTimeoutMs);
571596const child = spawn("bash", ["-c", command], {
572597cwd: ROOT_DIR,
573598detached: process.platform !== "win32",
@@ -593,27 +618,30 @@ export function runShellCommand({
593618console.error(`==> [${label}] ${message}; sending SIGTERM`);
594619}
595620terminateChild(child, "SIGTERM");
596-killAt = Date.now() + timeoutKillGraceMs;
597-killTimer = setTimeout(() => terminateChild(child, "SIGKILL"), timeoutKillGraceMs);
621+killAt = Date.now() + resolvedTimeoutKillGraceMs;
622+killTimer = setTimeout(
623+() => terminateChild(child, "SIGKILL"),
624+resolvedTimeoutKillGraceMs,
625+);
598626killTimer.unref?.();
599627};
600628const resetNoOutputTimer = () => {
601-if (!noOutputTimeoutMs || noOutputTimeoutMs <= 0 || timedOut) {
629+if (!resolvedNoOutputTimeoutMs || timedOut) {
602630return;
603631}
604632if (noOutputTimer) {
605633clearTimeout(noOutputTimer);
606634}
607635noOutputTimer = setTimeout(() => {
608-terminateForTimeout(`no output for ${noOutputTimeoutMs}ms`, { noOutput: true });
609-}, noOutputTimeoutMs);
636+terminateForTimeout(`no output for ${resolvedNoOutputTimeoutMs}ms`, { noOutput: true });
637+}, resolvedNoOutputTimeoutMs);
610638noOutputTimer.unref?.();
611639};
612640const timeoutTimer =
613-timeoutMs > 0
641+resolvedTimeoutMs !== undefined
614642 ? setTimeout(() => {
615-terminateForTimeout(`timeout after ${timeoutMs}ms`);
616-}, timeoutMs)
643+terminateForTimeout(`timeout after ${resolvedTimeoutMs}ms`);
644+}, resolvedTimeoutMs)
617645 : undefined;
618646timeoutTimer?.unref?.();
619647@@ -661,10 +689,10 @@ export function runShellCommand({
661689resolve({ signal, status: exitCode, timedOut, noOutputTimedOut });
662690};
663691if (timedOut) {
664-void finishTimedOutShellProcessTree(child, { killAt, timeoutKillGraceMs }).then(
665-finish,
666-finish,
667-);
692+void finishTimedOutShellProcessTree(child, {
693+killAt,
694+timeoutKillGraceMs: resolvedTimeoutKillGraceMs,
695+}).then(finish, finish);
668696return;
669697}
670698finish();
@@ -691,6 +719,11 @@ export function runShellCaptureCommand({
691719return activeChildrenShutdownPromise.then(() => shellCaptureSkippedForShutdown(label));
692720}
693721return new Promise((resolve) => {
722+const resolvedTimeoutMs = resolveOptionalTimerTimeoutMs(timeoutMs);
723+const resolvedTimeoutKillGraceMs = resolveTimerTimeoutMs(
724+timeoutKillGraceMs,
725+SHELL_TIMEOUT_KILL_GRACE_MS,
726+);
694727const child = spawn("bash", ["-c", command], {
695728cwd: ROOT_DIR,
696729detached: process.platform !== "win32",
@@ -706,14 +739,17 @@ export function runShellCaptureCommand({
706739let killTimer;
707740let killAt;
708741const timeoutTimer =
709-timeoutMs > 0
742+resolvedTimeoutMs !== undefined
710743 ? setTimeout(() => {
711744timedOut = true;
712745terminateChild(child, "SIGTERM");
713-killAt = Date.now() + timeoutKillGraceMs;
714-killTimer = setTimeout(() => terminateChild(child, "SIGKILL"), timeoutKillGraceMs);
746+killAt = Date.now() + resolvedTimeoutKillGraceMs;
747+killTimer = setTimeout(
748+() => terminateChild(child, "SIGKILL"),
749+resolvedTimeoutKillGraceMs,
750+);
715751killTimer.unref?.();
716-}, timeoutMs)
752+}, resolvedTimeoutMs)
717753 : undefined;
718754timeoutTimer?.unref?.();
719755child.stdout.on("data", (chunk) => {
@@ -749,10 +785,10 @@ export function runShellCaptureCommand({
749785});
750786};
751787if (timedOut) {
752-void finishTimedOutShellProcessTree(child, { killAt, timeoutKillGraceMs }).then(
753-finish,
754-finish,
755-);
788+void finishTimedOutShellProcessTree(child, {
789+killAt,
790+timeoutKillGraceMs: resolvedTimeoutKillGraceMs,
791+}).then(finish, finish);
756792return;
757793}
758794finish();
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。