mirror of
https://github.com/openclaw/openclaw.git
synced 2026-10-03 09:39:25 +00:00
fix(process): preserve the cause of cleanup observation failures (#140015)
Retain the original kernel observation error on the existing cleanup error. Keep classification, closure decisions and deadlines unchanged.
This commit is contained in:
parent
dc0578ae67
commit
c2ffbec6fc
2 changed files with 15 additions and 8 deletions
|
|
@ -466,11 +466,15 @@ it.each(["EPERM", "EIO", "still present"])(
|
|||
"keeps graceful cleanup uncertain when the kernel group is %s",
|
||||
async (failure) => {
|
||||
const { adapter, completeRoot, emit, close, groupProbe } = await createRelay("linux");
|
||||
const cause =
|
||||
failure === "still present"
|
||||
? undefined
|
||||
: Object.assign(new Error(`synthetic ${failure}`), { code: failure });
|
||||
groupProbe.mockImplementation(() => {
|
||||
if (failure === "still present") {
|
||||
return true;
|
||||
if (cause) {
|
||||
throw cause;
|
||||
}
|
||||
throw Object.assign(new Error(`synthetic ${failure}`), { code: failure });
|
||||
return true;
|
||||
});
|
||||
completeRoot();
|
||||
await expect(adapter.wait()).resolves.toEqual({ code: 0, signal: null });
|
||||
|
|
@ -480,6 +484,9 @@ it.each(["EPERM", "EIO", "still present"])(
|
|||
vi.spyOn(Date, "now").mockReturnValueOnce(10_000).mockReturnValue(15_000);
|
||||
close();
|
||||
await expect(adapter.waitForExtinction()).rejects.toThrow("owned process group");
|
||||
await expect(adapter.waitForExtinction()).rejects.toSatisfy(
|
||||
(error: unknown) => error instanceof Error && error.cause === cause,
|
||||
);
|
||||
await expect(adapter.wait()).resolves.toEqual({ code: 0, signal: null });
|
||||
expect(groupProbe).toHaveBeenCalledWith(-1235, 0);
|
||||
expect(groupProbe.mock.calls.every(([, signal]) => signal === 0)).toBe(true);
|
||||
|
|
|
|||
|
|
@ -255,12 +255,12 @@ export async function createServiceChildRelayAdapter(
|
|||
child.stderr?.once("end", settleWait);
|
||||
child.stderr?.once("close", settleWait);
|
||||
|
||||
const loseIdentity = (message: string) => {
|
||||
const loseIdentity = (message: string, options?: ErrorOptions) => {
|
||||
if (state === "closed" || state === "identity-lost") {
|
||||
return;
|
||||
}
|
||||
state = "identity-lost";
|
||||
waitError = new Error(`service child cleanup identity lost: ${message}`);
|
||||
waitError = new Error(`service child cleanup identity lost: ${message}`, options);
|
||||
events.emitError(waitError, "process");
|
||||
if (!commandPid) {
|
||||
startup.reject(waitError);
|
||||
|
|
@ -347,12 +347,12 @@ export async function createServiceChildRelayAdapter(
|
|||
try {
|
||||
// Observation only: signalling a retired numeric PGID could hit a reused group.
|
||||
process.kill(-anchorPid, 0);
|
||||
} catch (error) {
|
||||
} catch (cause) {
|
||||
// SAFETY: process.kill throws Node system errors; only the exact ESRCH code certifies absence.
|
||||
if ((error as NodeJS.ErrnoException).code === "ESRCH") {
|
||||
if ((cause as NodeJS.ErrnoException).code === "ESRCH") {
|
||||
finishAuthorityClose(missingReceiptError);
|
||||
} else {
|
||||
loseIdentity("owned process group disappearance could not be confirmed");
|
||||
loseIdentity("owned process group disappearance could not be confirmed", { cause });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue