From 2716bd96debda550cbbaa66867e930b738aaebe3 Mon Sep 17 00:00:00 2001 From: "paseo-bot[bot]" <266920839+paseo-bot[bot]@users.noreply.github.com> Date: Fri, 6 Nov 2026 06:27:04 +0000 Subject: [PATCH] test(terminal): observe original process completion after exit (#8892) Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com> --- .../src/terminal/terminal-worker-reaper.test.ts | 10 ++++++++++ .../src/terminal/worker-terminal-manager.test.ts | 13 ++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/server/src/terminal/terminal-worker-reaper.test.ts b/packages/server/src/terminal/terminal-worker-reaper.test.ts index a20d571b7f..66315b61d3 100644 --- a/packages/server/src/terminal/terminal-worker-reaper.test.ts +++ b/packages/server/src/terminal/terminal-worker-reaper.test.ts @@ -270,6 +270,16 @@ describe.skipIf(isPlatform("win32"))("terminal worker reaper", () => { await reapTerminalWorkers({ paseoHome: home, inspector, gracefulMs: 0 }); expect(isAlive(unrelated.pid!)).toBe(true); + // Completion means the recorded process is gone, even if its PID is occupied. + await expect + .poll( + async () => + !isAlive(original.pid) || + classifyTerminalProgramProcess(original, await inspector.inspect(original.pid)).status === + "unrelated", + { timeout: 10000 }, + ) + .toBe(true); expect(existsSync(recordPath)).toBe(false); expect( classifyTerminalProgramProcess(original, await inspector.inspect(original.pid)), diff --git a/packages/server/src/terminal/worker-terminal-manager.test.ts b/packages/server/src/terminal/worker-terminal-manager.test.ts index 0bcc2acf92..759f73e639 100644 --- a/packages/server/src/terminal/worker-terminal-manager.test.ts +++ b/packages/server/src/terminal/worker-terminal-manager.test.ts @@ -867,7 +867,18 @@ it.each([false, true])( writeFileSync(exitRequestPath, ""); await waitForCondition(() => first.getTerminal(ending.id) === undefined, 10000); expect(existsSync(exitObservedPath)).toBe(true); - expect(isProcessAlive(endingPid)).toBe(false); + const originalEnding = record!.terminals.find((entry) => entry.id === ending.id)!; + // Exit delivery does not reserve the PID. Wait for the original process to + // disappear, allowing Windows to reuse its PID just as in the restart check below. + await expect + .poll( + async () => + !isProcessAlive(endingPid) || + classifyTerminalProgramProcess(originalEnding, await inspector.inspect(endingPid)) + .status === "unrelated", + { timeout: 10000 }, + ) + .toBe(true); } finally { if (recordFd !== null) closeSync(recordFd); }