From 4febe1d420712e7bc69ea6dc97bf608d633e5f40 Mon Sep 17 00:00:00 2001 From: 4gray Date: Mon, 28 Sep 2026 22:05:23 +0200 Subject: [PATCH] test(e2e): skip killing an Electron that already exited stopElectron now checks the recorded exit state before each signal and tolerates a kill that races the exit: on Windows taskkill throws for a PID that no longer exists. Startup cleanup can no longer replace the startup error that explains the failure; a cleanup failure there is logged. Co-Authored-By: Claude Opus 5.5 --- .../src/electron-unautomated-launch.ts | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/apps/electron-backend-e2e/src/electron-unautomated-launch.ts b/apps/electron-backend-e2e/src/electron-unautomated-launch.ts index 7abb8ad19..6f1d6428c 100644 --- a/apps/electron-backend-e2e/src/electron-unautomated-launch.ts +++ b/apps/electron-backend-e2e/src/electron-unautomated-launch.ts @@ -172,12 +172,25 @@ async function stopElectron( child: ChildProcess, exited: Promise ): Promise { + let lastKillError: unknown; for (const signal of ['SIGTERM', 'SIGKILL'] as const) { - terminateElectronProcess(child, signal); + // Already gone (exited on its own, or during startup): nothing to + // kill. On Windows taskkill throws for a PID that no longer exists. + if (await waitForExit(child, exited, 0)) return; + try { + terminateElectronProcess(child, signal); + } catch (error) { + // The process may have exited between the check and the kill. + lastKillError = error; + } if (await waitForExit(child, exited, EXIT_WAIT_MS)) return; } + const killFailure = + lastKillError === undefined + ? '' + : ` (last kill: ${String(lastKillError)})`; throw new Error( - `Electron (pid ${child.pid}) did not exit after SIGTERM and SIGKILL` + `Electron (pid ${child.pid}) did not exit after SIGTERM and SIGKILL${killFailure}` ); } @@ -220,7 +233,10 @@ export async function launchUnautomatedElectronApp( }, }; } catch (error) { - await stopElectron(child, exited); + // Cleanup must never replace the startup failure that explains the test. + await stopElectron(child, exited).catch((cleanupError: unknown) => + console.warn('Unautomated Electron cleanup failed:', cleanupError) + ); throw error; } }