Skip to content

Commit 9a83733

Browse files
committed
fix(browser): guard graceful close process ownership
1 parent 68542cb commit 9a83733

2 files changed

Lines changed: 24 additions & 2 deletions

File tree

extensions/browser/src/browser/chrome.test.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,17 @@ async function stopChromeWithProc(proc: ReturnType<typeof makeChromeTestProc>, t
138138
);
139139
}
140140

141-
function makeChromeTestProc(overrides?: Partial<{ killed: boolean; exitCode: number | null }>) {
141+
function makeChromeTestProc(
142+
overrides?: Partial<{
143+
killed: boolean;
144+
exitCode: number | null;
145+
signalCode: NodeJS.Signals | null;
146+
}>,
147+
) {
142148
return {
143149
killed: overrides?.killed ?? false,
144150
exitCode: overrides?.exitCode ?? null,
151+
signalCode: overrides?.signalCode ?? null,
145152
kill: vi.fn(),
146153
};
147154
}
@@ -884,6 +891,19 @@ describe("browser chrome helpers", () => {
884891
expect(proc.kill).not.toHaveBeenCalled();
885892
});
886893

894+
it.each([
895+
{ label: "exited", proc: makeChromeTestProc({ exitCode: 0 }) },
896+
{ label: "signaled", proc: makeChromeTestProc({ signalCode: "SIGTERM" }) },
897+
])("does not close a reused CDP port after the tracked process has $label", async ({ proc }) => {
898+
const fetchMock = vi.fn();
899+
vi.stubGlobal("fetch", fetchMock);
900+
901+
await stopChromeWithProc(proc, 10);
902+
903+
expect(fetchMock).not.toHaveBeenCalled();
904+
expect(proc.kill).not.toHaveBeenCalled();
905+
});
906+
887907
it("stopOpenClawChrome sends SIGTERM and returns once CDP is down", async () => {
888908
vi.stubGlobal("fetch", vi.fn().mockRejectedValue(new Error("down")));
889909
const proc = makeChromeTestProc();

extensions/browser/src/browser/chrome.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1204,7 +1204,9 @@ export async function stopOpenClawChrome(
12041204
) {
12051205
const proc = running.proc;
12061206
try {
1207-
if (proc.killed) {
1207+
// The fixed CDP port may already belong to a replacement. Once the
1208+
// tracked child exits, never send Browser.close to the current listener.
1209+
if (proc.killed || proc.exitCode != null || proc.signalCode != null) {
12081210
return;
12091211
}
12101212

0 commit comments

Comments
 (0)