fix(scripts): guard delayed docker package kills

This commit is contained in:
Vincent Koc
2026-06-01 23:33:00 +02:00
parent 2405bbcbaf
commit 72ed2121f8
2 changed files with 50 additions and 2 deletions

View File

@@ -142,10 +142,27 @@ function run(command, args, cwd, options = {}) {
}
child.kill(signal);
};
const processGroupAlive = () => {
if (!useProcessGroup || !child.pid) {
return false;
}
try {
process.kill(-child.pid, 0);
return true;
} catch (error) {
return error?.code === "EPERM";
}
};
const terminateChild = () => {
killChild("SIGTERM");
forceKillTimeout = setTimeout(
() => killChild("SIGKILL"),
() => {
forceKillTimeout = undefined;
if (settled && !processGroupAlive()) {
return;
}
killChild("SIGKILL");
},
options.killAfterMs ?? DEFAULT_TIMEOUT_KILL_AFTER_MS,
);
forceKillTimeout.unref?.();

View File

@@ -3,7 +3,7 @@ import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { pathToFileURL } from "node:url";
import { describe, expect, it } from "vitest";
import { describe, expect, it, vi } from "vitest";
import {
buildPackageArtifacts,
packOpenClawPackageForDocker,
@@ -246,6 +246,37 @@ describe("package-openclaw-for-docker", () => {
}
});
it("does not fire delayed SIGKILL after a timed-out child exits during grace", async () => {
if (process.platform === "win32") {
return;
}
const killSpy = vi.spyOn(process, "kill");
try {
const script = [
"process.on('SIGTERM', () => process.exit(0));",
"setInterval(() => {}, 1000);",
].join("");
await expect(
runCommandForTest(process.execPath, ["-e", script], process.cwd(), {
killAfterMs: 100,
timeoutMs: 25,
}),
).rejects.toThrow(/timed out after 25ms/u);
const sigkillCallsAfterExit = killSpy.mock.calls.filter(
([, signal]) => signal === "SIGKILL",
).length;
await sleep(150);
expect(killSpy.mock.calls.filter(([, signal]) => signal === "SIGKILL")).toHaveLength(
sigkillCallsAfterExit,
);
} finally {
killSpy.mockRestore();
}
});
it("fails captured commands that exceed the stdout limit", async () => {
const script = [
"process.stdout.write('x'.repeat(2048));",