From 30a209aab5bf6be6337a371936fe1118798824e1 Mon Sep 17 00:00:00 2001 From: Huanqi Cao Date: Tue, 7 Jul 2026 01:22:30 +0800 Subject: [PATCH] fix(e2e): reach child quiescence before temp-dir cleanup in built-bin smokes The acp built-bin smoke killed its child and immediately rm'd the temp consumer dir; POSIX tolerates unlinking a live process's cwd, Windows fails EBUSY while the child still holds its cwd and session-log handles (the CI windows job's only red step). Await the child's exit after SIGKILL and give both smokes' rm a brief retry for the OS handle-release lag. --- packages/examples/acp-demo/tests/built-bin.e2e.ts | 15 +++++++++++++-- .../examples/stdio-demo/tests/built-bin.e2e.ts | 3 ++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/packages/examples/acp-demo/tests/built-bin.e2e.ts b/packages/examples/acp-demo/tests/built-bin.e2e.ts index 7b5749fee5..9e799b29db 100644 --- a/packages/examples/acp-demo/tests/built-bin.e2e.ts +++ b/packages/examples/acp-demo/tests/built-bin.e2e.ts @@ -95,8 +95,19 @@ let consumer: string | undefined let child: ReturnType | undefined afterEach(async () => { - if (child !== undefined) { child.kill('SIGKILL'); child = undefined } - if (consumer !== undefined) await rm(consumer, { recursive: true, force: true }) + if (child !== undefined) { + const proc = child + child = undefined + // Windows retains the child's cwd and session-log handles until process + // teardown completes, so await exit before removing the temp directory. + if (proc.exitCode === null && proc.signalCode === null) { + const exited = new Promise((resolve) => { proc.once('exit', () => { resolve() }) }) + proc.kill('SIGKILL') + await exited + } + } + // Windows can briefly retain released handles after exit; retry removal. + if (consumer !== undefined) await rm(consumer, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }) consumer = undefined }) diff --git a/packages/examples/stdio-demo/tests/built-bin.e2e.ts b/packages/examples/stdio-demo/tests/built-bin.e2e.ts index fdbeb2b8e4..ec14440b18 100644 --- a/packages/examples/stdio-demo/tests/built-bin.e2e.ts +++ b/packages/examples/stdio-demo/tests/built-bin.e2e.ts @@ -116,7 +116,8 @@ function runBuiltBin(cwd: string, configArg: string, line: string): Promise<{ st let consumer: string | undefined afterEach(async () => { - if (consumer !== undefined) await rm(consumer, { recursive: true, force: true }) + // Windows can briefly retain released handles after exit; retry removal. + if (consumer !== undefined) await rm(consumer, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }) consumer = undefined })