* exec: clean up PTY resources on timeout and exit * cli: harden resume cleanup and watchdog stalled runs * cli: productionize PTY and resume reliability paths * docs: add PTY process supervision architecture plan * docs: rewrite PTY supervision plan as pre-rewrite baseline * docs: switch PTY supervision plan to one-go execution * docs: add one-line root cause to PTY supervision plan * docs: add OS contracts and test matrix to PTY supervision plan * docs: define process-supervisor package placement and scope * docs: tie supervisor plan to existing CI lanes * docs: place PTY supervisor plan under src/process * refactor(process): route exec and cli runs through supervisor * docs(process): refresh PTY supervision plan * wip * fix(process): harden supervisor timeout and PTY termination * fix(process): harden supervisor adapters env and wait handling * ci: avoid failing formal conformance on comment permissions * test(ui): fix cron request mock argument typing * fix(ui): remove leftover conflict marker * fix: supervise PTY processes (#14257) (openclaw#14257) (thanks @onutc)
35 lines
736 B
TypeScript
35 lines
736 B
TypeScript
import { spawn } from "node:child_process";
|
|
|
|
/**
|
|
* Best-effort process-tree termination.
|
|
* - Windows: use taskkill /T to include descendants.
|
|
* - Unix: try process-group kill first, then direct pid kill.
|
|
*/
|
|
export function killProcessTree(pid: number): void {
|
|
if (!Number.isFinite(pid) || pid <= 0) {
|
|
return;
|
|
}
|
|
|
|
if (process.platform === "win32") {
|
|
try {
|
|
spawn("taskkill", ["/F", "/T", "/PID", String(pid)], {
|
|
stdio: "ignore",
|
|
detached: true,
|
|
});
|
|
} catch {
|
|
// ignore taskkill failures
|
|
}
|
|
return;
|
|
}
|
|
|
|
try {
|
|
process.kill(-pid, "SIGKILL");
|
|
} catch {
|
|
try {
|
|
process.kill(pid, "SIGKILL");
|
|
} catch {
|
|
// process already gone or inaccessible
|
|
}
|
|
}
|
|
}
|