diff --git a/packages/adapter-utils/src/server-utils.test.ts b/packages/adapter-utils/src/server-utils.test.ts index e96df8c8b79..4579e1672a7 100644 --- a/packages/adapter-utils/src/server-utils.test.ts +++ b/packages/adapter-utils/src/server-utils.test.ts @@ -157,6 +157,35 @@ describe("runChildProcess", () => { expect(await waitForPidExit(descendantPid, 2_000)).toBe(true); }); + it.skipIf(process.platform === "win32")("cleans up a still-running child after terminal output", async () => { + const result = await runChildProcess( + randomUUID(), + process.execPath, + [ + "-e", + [ + "process.stdout.write(`${JSON.stringify({ type: 'result', result: 'done' })}\\n`);", + "setInterval(() => {}, 1000);", + ].join(" "), + ], + { + cwd: process.cwd(), + env: {}, + timeoutSec: 0, + graceSec: 1, + onLog: async () => {}, + terminalResultCleanup: { + graceMs: 100, + hasTerminalResult: ({ stdout }) => stdout.includes('"type":"result"'), + }, + }, + ); + + expect(result.timedOut).toBe(false); + expect(result.signal).toBe("SIGTERM"); + expect(result.stdout).toContain('"type":"result"'); + }); + it.skipIf(process.platform === "win32")("does not clean up noisy runs that have no terminal output", async () => { const runId = randomUUID(); let observed = ""; diff --git a/packages/adapter-utils/src/server-utils.ts b/packages/adapter-utils/src/server-utils.ts index c6fc3ea8ec0..88acc936a9a 100644 --- a/packages/adapter-utils/src/server-utils.ts +++ b/packages/adapter-utils/src/server-utils.ts @@ -1345,7 +1345,6 @@ export async function runChildProcess( let stdout = ""; let stderr = ""; let logChain: Promise = Promise.resolve(); - let childExited = false; let terminalResultSeen = false; let terminalCleanupStarted = false; let terminalCleanupTimer: NodeJS.Timeout | null = null; @@ -1379,7 +1378,7 @@ export async function runChildProcess( onLogError(err, runId, "failed to inspect terminal adapter output"); } } - if (!terminalResultSeen || !childExited) return; + if (!terminalResultSeen) return; if (terminalCleanupTimer) return; const graceMs = Math.max(0, terminalCleanup.graceMs ?? 5_000); @@ -1462,7 +1461,6 @@ export async function runChildProcess( }); child.on("exit", () => { - childExited = true; maybeArmTerminalResultCleanup(); });