From 0161cd6325a05742c0d7be351fcb20efff63ca8b Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Sun, 6 Sep 2026 03:19:18 -0700 Subject: [PATCH] diagnostic: trace Git Bash fixture shutdown ownership --- tests/e2e/helpers/electron-process-shutdown.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tests/e2e/helpers/electron-process-shutdown.ts b/tests/e2e/helpers/electron-process-shutdown.ts index f9b642a676e..cae5689833e 100644 --- a/tests/e2e/helpers/electron-process-shutdown.ts +++ b/tests/e2e/helpers/electron-process-shutdown.ts @@ -1,3 +1,4 @@ +import { readWindowsProcessTableFresh } from '../../../src/main/windows/windows-process-table' import type { ChildProcess } from 'node:child_process' import { execFileSync } from 'node:child_process' import { existsSync, readFileSync, readdirSync } from 'node:fs' @@ -5,6 +6,15 @@ import path from 'node:path' import { cleanupE2ECrashpad } from './electron-crashpad-cleanup' import type { ElectronApplication } from '@stablyai/playwright-test' + +async function reportShutdownTree(label: string, rootPid?: number): Promise { + if (process.platform !== 'win32') return + const rows = await readWindowsProcessTableFresh() + const selected = rows.filter((row) => /golden-stub|terminal-host|orca.*daemon/i.test(row.command) || row.pid === rootPid) + const parents = new Set(selected.map((row) => row.ppid)) + console.error('SHUTDOWN_TREE', label, rootPid, JSON.stringify(rows.filter((row) => selected.includes(row) || parents.has(row.pid)))) +} + const GRACEFUL_CLOSE_TIMEOUT_MS = 10_000 const PROCESS_EXIT_TIMEOUT_MS = 5_000 const FORCE_KILL_WAIT_MS = 2_000 @@ -184,6 +194,7 @@ export async function forceQuitElectronAppForE2E(app: ElectronApplication): Prom export async function closeElectronAppForE2E(app: ElectronApplication): Promise { const proc = app.process() + await reportShutdownTree('before-app-close', proc.pid) const releasePipes = (): void => releaseExitedProcessPipes(proc) proc.once('exit', releasePipes) releasePipes() @@ -236,8 +247,12 @@ export async function cleanupE2EDaemons(userDataDir: string): Promise { // Why: app quit intentionally leaves daemon PTYs alive for warm reattach. // E2E temp profiles are deleted after each test, so their detached daemons // must be stopped explicitly or CI accumulates orphan Electron/shell trees. - for (const pid of readDaemonPidFiles(userDataDir)) { + const daemonPids = readDaemonPidFiles(userDataDir) + console.error('DAEMON_PID_FILES', userDataDir, daemonPids) + await reportShutdownTree('before-daemon-cleanup') + for (const pid of daemonPids) { await forceKillPidTree(pid) } + await reportShutdownTree('after-daemon-cleanup') cleanupE2ECrashpad(userDataDir) }