diagnostic: inspect native Git Bash job ownership

This commit is contained in:
Neil
2026-09-06 03:31:25 -07:00
parent 2d05389a09
commit c08903bcfb
2 changed files with 15 additions and 2 deletions
@@ -1,10 +1,13 @@
import { appendFileSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import * as pty from 'node-pty'
import {
hostReportsChildExitStatus,
wrapShellSpawnForMacosTccAttribution
} from '../../providers/macos-tcc-login-shell'
import type { WindowsShellSpawnAttempt } from '../../providers/windows-shell-fallback-chain'
import { assignHostProcessToKillOnCloseJob } from '../../windows/windows-pty-job'
import { assignHostProcessToKillOnCloseJob, listPtyJobProcessIds, isPtyJobOwnershipAvailable } from '../../windows/windows-pty-job'
export type SpawnedDaemonPty = {
process: pty.IPty
@@ -31,7 +34,7 @@ export function spawnNativeDaemonPty(args: {
const wrapped = wrapShellSpawnForMacosTccAttribution(shellPath, shellArgs, args.env)
// Why: children inherit job membership, so the host job must exist before the first Windows PTY.
if (process.platform === 'win32') {
assignHostProcessToKillOnCloseJob()
appendFileSync(join(tmpdir(), 'orca-pty-job-diagnostic.jsonl'), JSON.stringify({ event: 'host-job', pid: process.pid, available: isPtyJobOwnershipAvailable(), assigned: assignHostProcessToKillOnCloseJob() }) + '\n')
}
const proc = pty.spawn(wrapped.file, wrapped.args, {
name: args.env.TERM ?? 'xterm-256color',
@@ -42,6 +45,13 @@ export function spawnNativeDaemonPty(args: {
// Why: bundled ConPTY has the wrap-marker behavior xterm expects.
...(process.platform === 'win32' ? { useConptyDll: true } : {})
})
if (process.platform === 'win32') {
const report = (event: string): void => {
appendFileSync(join(tmpdir(), 'orca-pty-job-diagnostic.jsonl'), JSON.stringify({ event, host: process.pid, shell: proc.pid, shellPath, members: listPtyJobProcessIds(proc) }) + '\n')
}
report('spawn-job')
setTimeout(() => report('job-after-launch'), 3000).unref()
}
reportsChildExitStatus = hostReportsChildExitStatus(wrapped.file)
args.onMacosTccSpawnStrategy?.(wrapped.file === shellPath ? 'direct' : 'wrapped')
return proc
@@ -1,3 +1,4 @@
import { tmpdir } from 'node:os'
import { readWindowsProcessTableFresh } from '../../../src/main/windows/windows-process-table'
import type { ChildProcess } from 'node:child_process'
import { execFileSync } from 'node:child_process'
@@ -247,6 +248,8 @@ export async function cleanupE2EDaemons(userDataDir: string): Promise<void> {
// 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.
const jobLog = path.join(tmpdir(), 'orca-pty-job-diagnostic.jsonl')
if (existsSync(jobLog)) console.error('NATIVE_JOB_DIAGNOSTIC', readFileSync(jobLog, 'utf8'))
const daemonPids = readDaemonPidFiles(userDataDir)
console.error('DAEMON_PID_FILES', userDataDir, daemonPids)
await reportShutdownTree('before-daemon-cleanup')