mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 08:02:28 +00:00
68 lines
2.0 KiB
TypeScript
68 lines
2.0 KiB
TypeScript
import { spawn, type ChildProcess } from 'node:child_process'
|
|
import { admitSelfInitiatedTreeKill } from '../../own-chromium-tree-kill-guard'
|
|
|
|
const WINDOWS_TREE_KILL_WAIT_MS = 2_000
|
|
|
|
export function killSpawnedCommandTree(child: ChildProcess): Promise<void> {
|
|
const pid = child.pid
|
|
if (!pid || process.platform !== 'win32') {
|
|
child.kill()
|
|
return Promise.resolve()
|
|
}
|
|
// Windows may reuse the pid after exit while inherited pipes still delay close.
|
|
if ((child.exitCode ?? null) !== null || (child.signalCode ?? null) !== null) {
|
|
child.kill()
|
|
return Promise.resolve()
|
|
}
|
|
if (
|
|
!admitSelfInitiatedTreeKill({ pid, site: 'git-command-tree-kill', scope: 'win-taskkill-tree' })
|
|
) {
|
|
// Refusal blocks the pid-addressed tree walk, never the termination: the
|
|
// handle-addressed root kill cannot reach a recycled pid.
|
|
child.kill()
|
|
return Promise.resolve()
|
|
}
|
|
return new Promise((resolve) => {
|
|
let killer: ChildProcess
|
|
try {
|
|
// Why: Windows shims/wsl.exe own descendants; wait for /t tree cleanup so a timed-out command can't outlive its probe.
|
|
killer = spawn('taskkill', ['/pid', String(pid), '/t', '/f'], {
|
|
stdio: 'ignore',
|
|
windowsHide: true
|
|
})
|
|
if (!killer || typeof killer.unref !== 'function') {
|
|
child.kill()
|
|
resolve()
|
|
return
|
|
}
|
|
} catch {
|
|
child.kill()
|
|
resolve()
|
|
return
|
|
}
|
|
let settled = false
|
|
let timer: NodeJS.Timeout | null = null
|
|
const finish = (fallbackToChildKill: boolean): void => {
|
|
if (settled) {
|
|
return
|
|
}
|
|
settled = true
|
|
if (timer) {
|
|
clearTimeout(timer)
|
|
}
|
|
killer.removeAllListeners()
|
|
if (fallbackToChildKill) {
|
|
child.kill()
|
|
}
|
|
resolve()
|
|
}
|
|
killer.once('error', () => finish(true))
|
|
killer.once('close', (code) => finish(code !== 0))
|
|
timer = setTimeout(() => {
|
|
killer.kill()
|
|
finish(true)
|
|
}, WINDOWS_TREE_KILL_WAIT_MS)
|
|
killer.unref()
|
|
})
|
|
}
|