

























@@ -25,6 +25,7 @@ const COMMAND_TIMEOUT_MS = readPositiveInt(
2525120000,
2626"OPENCLAW_SECRET_PROOF_COMMAND_MS",
2727);
28+const COMMAND_TIMEOUT_KILL_GRACE_MS = 1000;
2829const READY_TIMEOUT_MS = readPositiveInt(
2930process.env.OPENCLAW_SECRET_PROOF_READY_MS,
3031120000,
@@ -297,20 +298,27 @@ function runCommand(command, args, options = {}) {
297298let timedOut = false;
298299let aborted = false;
299300let killTimer;
301+let forceKillAt;
302+const armForceKill = () => {
303+forceKillAt ??= Date.now() + COMMAND_TIMEOUT_KILL_GRACE_MS;
304+killTimer ??= setTimeout(
305+() => terminateProcessTree(child, "SIGKILL"),
306+COMMAND_TIMEOUT_KILL_GRACE_MS,
307+);
308+killTimer.unref();
309+};
300310const abort = () => {
301311if (usesProcessGroup ? !processTreeIsAlive(child) : childHasExited(child)) {
302312return;
303313}
304314aborted = true;
305315terminateProcessTree(child, "SIGTERM");
306-killTimer ??= setTimeout(() => terminateProcessTree(child, "SIGKILL"), 1000);
307-killTimer.unref();
316+armForceKill();
308317};
309318const timer = setTimeout(() => {
310319timedOut = true;
311320terminateProcessTree(child, "SIGTERM");
312-killTimer = setTimeout(() => terminateProcessTree(child, "SIGKILL"), 1000);
313-killTimer.unref();
321+armForceKill();
314322}, timeoutMs);
315323const abortSignal = options.signal;
316324if (abortSignal?.aborted) {
@@ -347,27 +355,42 @@ function runCommand(command, args, options = {}) {
347355if (killTimer) {
348356clearTimeout(killTimer);
349357}
358+forceKillAt = undefined;
350359abortSignal?.removeEventListener("abort", abort);
351360removeParentSignalHandlers();
352361reject(error instanceof Error ? error : new Error(formatErrorMessage(error)));
353362});
354363child.on("close", (code, signal) => {
355364clearTimeout(timer);
356-if (killTimer) {
357-clearTimeout(killTimer);
358-}
359365abortSignal?.removeEventListener("abort", abort);
360366removeParentSignalHandlers();
361367const result = { code, signal, stdout: stdout.text(), stderr: stderr.text() };
368+const finishTerminatedTree = async () => {
369+await finishTimedOutCommandProcessTree(child, {
370+ forceKillAt,
371+timeoutKillGraceMs: COMMAND_TIMEOUT_KILL_GRACE_MS,
372+});
373+if (killTimer) {
374+clearTimeout(killTimer);
375+}
376+forceKillAt = undefined;
377+};
362378if (aborted) {
363-reject(new Error(scrub(`command aborted: ${command} ${args.join(" ")}`)));
379+void finishTerminatedTree().finally(() =>
380+reject(new Error(scrub(`command aborted: ${command} ${args.join(" ")}`))),
381+);
364382return;
365383}
366384if (timedOut) {
367-terminateProcessTree(child, "SIGKILL");
368-reject(new Error(scrub(`command timed out: ${command} ${args.join(" ")}`)));
385+void finishTerminatedTree().finally(() =>
386+reject(new Error(scrub(`command timed out: ${command} ${args.join(" ")}`))),
387+);
369388return;
370389}
390+if (killTimer) {
391+clearTimeout(killTimer);
392+}
393+forceKillAt = undefined;
371394if (result.signal && options.allowFailure !== true) {
372395reject(
373396new Error(
@@ -880,6 +903,21 @@ async function stopGateway(child) {
880903await waitForProcessTreeExit(child, 1000);
881904}
882905906+async function finishTimedOutCommandProcessTree(child, { forceKillAt, timeoutKillGraceMs }) {
907+if (!processTreeIsAlive(child)) {
908+return;
909+}
910+const graceRemainingMs =
911+forceKillAt === undefined ? timeoutKillGraceMs : Math.max(0, forceKillAt - Date.now());
912+if (graceRemainingMs > 0) {
913+await waitForProcessTreeExit(child, graceRemainingMs);
914+}
915+if (processTreeIsAlive(child)) {
916+terminateProcessTree(child, "SIGKILL");
917+}
918+await waitForProcessTreeExit(child, timeoutKillGraceMs);
919+}
920+883921function childHasExited(child) {
884922return child.exitCode !== null || child.signalCode !== null;
885923}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。