mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-21 10:16:44 +00:00
test: ignore ESRCH during process cleanup (#106880)
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
// Tests race-safe process cleanup helpers.
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { killPidIfAlive } from "./process-tree.js";
|
||||
|
||||
describe("killPidIfAlive", () => {
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("ignores ESRCH when a live process exits before SIGKILL", () => {
|
||||
const killError = Object.assign(new Error("kill ESRCH"), { code: "ESRCH" });
|
||||
const kill = vi
|
||||
.spyOn(process, "kill")
|
||||
.mockReturnValueOnce(true)
|
||||
.mockImplementationOnce(() => {
|
||||
throw killError;
|
||||
});
|
||||
|
||||
expect(() => killPidIfAlive(123)).not.toThrow();
|
||||
expect(kill).toHaveBeenNthCalledWith(1, 123, 0);
|
||||
expect(kill).toHaveBeenNthCalledWith(2, 123, "SIGKILL");
|
||||
});
|
||||
|
||||
it("rethrows other SIGKILL failures", () => {
|
||||
const killError = Object.assign(new Error("kill EPERM"), { code: "EPERM" });
|
||||
vi.spyOn(process, "kill")
|
||||
.mockReturnValueOnce(true)
|
||||
.mockImplementationOnce(() => {
|
||||
throw killError;
|
||||
});
|
||||
|
||||
expect(() => killPidIfAlive(123)).toThrow(killError);
|
||||
});
|
||||
});
|
||||
@@ -52,5 +52,12 @@ export function killPidIfAlive(pid: number | undefined): void {
|
||||
if (pid === undefined || !isPidAlive(pid)) {
|
||||
return;
|
||||
}
|
||||
process.kill(pid, "SIGKILL");
|
||||
try {
|
||||
process.kill(pid, "SIGKILL");
|
||||
} catch (error) {
|
||||
// The process can exit after the liveness probe; ESRCH already satisfies cleanup.
|
||||
if ((error as NodeJS.ErrnoException | undefined)?.code !== "ESRCH") {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,7 +215,14 @@ function killPidIfAlive(pid: number | undefined): void {
|
||||
if (pid === undefined || !pidIsAlive(pid)) {
|
||||
return;
|
||||
}
|
||||
process.kill(pid, "SIGKILL");
|
||||
try {
|
||||
process.kill(pid, "SIGKILL");
|
||||
} catch (error) {
|
||||
// The process can exit after the liveness probe; ESRCH already satisfies cleanup.
|
||||
if ((error as NodeJS.ErrnoException | undefined)?.code !== "ESRCH") {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
@@ -249,6 +256,20 @@ describe("bundled plugin install/uninstall probe", () => {
|
||||
expect(kill).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("ignores ESRCH when a probed process exits before cleanup", () => {
|
||||
const killError = Object.assign(new Error("kill ESRCH"), { code: "ESRCH" });
|
||||
const kill = vi
|
||||
.spyOn(process, "kill")
|
||||
.mockReturnValueOnce(true)
|
||||
.mockImplementationOnce(() => {
|
||||
throw killError;
|
||||
});
|
||||
|
||||
expect(() => killPidIfAlive(123)).not.toThrow();
|
||||
expect(kill).toHaveBeenNthCalledWith(1, 123, 0);
|
||||
expect(kill).toHaveBeenNthCalledWith(2, 123, "SIGKILL");
|
||||
});
|
||||
|
||||
it("keeps the sweep script compatible with macOS Bash 3", () => {
|
||||
const sweep = fs.readFileSync(sweepPath, "utf8");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user