mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-07 01:44:04 +02:00
Harden exec completion after child exit
This commit is contained in:
@@ -246,6 +246,8 @@ export async function runCommandWithTimeout(
|
||||
let settled = false;
|
||||
let timedOut = false;
|
||||
let noOutputTimedOut = false;
|
||||
let childExitState: { code: number | null; signal: NodeJS.Signals | null } | null = null;
|
||||
let closeFallbackTimer: NodeJS.Timeout | null = null;
|
||||
let noOutputTimer: NodeJS.Timeout | null = null;
|
||||
const shouldTrackOutputTimeout =
|
||||
typeof noOutputTimeoutMs === "number" &&
|
||||
@@ -260,6 +262,14 @@ export async function runCommandWithTimeout(
|
||||
noOutputTimer = null;
|
||||
};
|
||||
|
||||
const clearCloseFallbackTimer = () => {
|
||||
if (!closeFallbackTimer) {
|
||||
return;
|
||||
}
|
||||
clearTimeout(closeFallbackTimer);
|
||||
closeFallbackTimer = null;
|
||||
};
|
||||
|
||||
const armNoOutputTimer = () => {
|
||||
if (!shouldTrackOutputTimeout || settled) {
|
||||
return;
|
||||
@@ -304,8 +314,22 @@ export async function runCommandWithTimeout(
|
||||
settled = true;
|
||||
clearTimeout(timer);
|
||||
clearNoOutputTimer();
|
||||
clearCloseFallbackTimer();
|
||||
reject(err);
|
||||
});
|
||||
child.on("exit", (code, signal) => {
|
||||
childExitState = { code, signal };
|
||||
if (settled || closeFallbackTimer) {
|
||||
return;
|
||||
}
|
||||
closeFallbackTimer = setTimeout(() => {
|
||||
if (settled) {
|
||||
return;
|
||||
}
|
||||
child.stdout?.destroy();
|
||||
child.stderr?.destroy();
|
||||
}, 250);
|
||||
});
|
||||
child.on("close", (code, signal) => {
|
||||
if (settled) {
|
||||
return;
|
||||
@@ -313,25 +337,28 @@ export async function runCommandWithTimeout(
|
||||
settled = true;
|
||||
clearTimeout(timer);
|
||||
clearNoOutputTimer();
|
||||
clearCloseFallbackTimer();
|
||||
const resolvedCode = childExitState?.code ?? code;
|
||||
const resolvedSignal = childExitState?.signal ?? signal;
|
||||
const termination = noOutputTimedOut
|
||||
? "no-output-timeout"
|
||||
: timedOut
|
||||
? "timeout"
|
||||
: signal != null
|
||||
: resolvedSignal != null
|
||||
? "signal"
|
||||
: "exit";
|
||||
const normalizedCode =
|
||||
termination === "timeout" || termination === "no-output-timeout"
|
||||
? code === 0
|
||||
? resolvedCode === 0
|
||||
? 124
|
||||
: code
|
||||
: code;
|
||||
: resolvedCode
|
||||
: resolvedCode;
|
||||
resolve({
|
||||
pid: child.pid ?? undefined,
|
||||
stdout,
|
||||
stderr,
|
||||
code: normalizedCode,
|
||||
signal,
|
||||
signal: resolvedSignal,
|
||||
killed: child.killed,
|
||||
termination,
|
||||
noOutputTimedOut,
|
||||
|
||||
Reference in New Issue
Block a user