mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-05 00:56:23 +00:00
- Blocker: arm 3s force-exit timer BEFORE awaiting cleanup, not
inside .finally(). Prevents hang if drainBrowserPool() blocks on
dead Chrome.
- Reorder cleanup: killTrackedProcesses() (sync, fast) runs first,
then async browser drain. Ffmpeg dies immediately instead of
surviving if the hard timer fires early.
- SIGKILL escalation: processTracker now SIGTERMs all tracked
processes, then SIGKILLs survivors after 500ms grace period.
- Scope pgrep to current user (pgrep -u $(id -u)) so orphan
detection doesn't touch other users' Chrome on shared machines.
- Add process.on('exit') handler for crash paths (unhandled
exceptions/rejections that bypass signal handlers).
- Document Windows no-op behavior on killProcessTree handlers.
42 lines
925 B
TypeScript
42 lines
925 B
TypeScript
import type { ChildProcess } from "node:child_process";
|
|
|
|
const tracked = new Set<ChildProcess>();
|
|
|
|
export function trackChildProcess(proc: ChildProcess): void {
|
|
tracked.add(proc);
|
|
const remove = () => tracked.delete(proc);
|
|
proc.once("exit", remove);
|
|
proc.once("error", remove);
|
|
}
|
|
|
|
/**
|
|
* SIGTERM all tracked child processes, then SIGKILL any that survive
|
|
* after a short grace period.
|
|
*/
|
|
export function killTrackedProcesses(): void {
|
|
const alive: ChildProcess[] = [];
|
|
for (const proc of tracked) {
|
|
if (!proc.killed) {
|
|
try {
|
|
proc.kill("SIGTERM");
|
|
alive.push(proc);
|
|
} catch {
|
|
// Already exited between the check and the kill.
|
|
}
|
|
}
|
|
}
|
|
tracked.clear();
|
|
|
|
if (alive.length === 0) return;
|
|
|
|
setTimeout(() => {
|
|
for (const proc of alive) {
|
|
try {
|
|
proc.kill("SIGKILL");
|
|
} catch {
|
|
// Already exited.
|
|
}
|
|
}
|
|
}, 500).unref();
|
|
}
|