Something went wrong. Try again.
I'm going to build my own OpenClaw, with blackjack... and bun!
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495/** * utils/process-tracker.ts – Registry of spawned child processes. * * Tracks PIDs of child processes spawned by the agent (bash commands, scripts) * so they can be force-killed when an agent turn is cancelled or the * application is shutting down. * * Consumers: * - tools/tracked-bash.ts registers/unregisters PIDs around each bash exec. * - agent-pool.ts calls killTrackedProcesses() when aborting an agent run. * - runtime.ts calls killTrackedProcesses() on graceful shutdown. */
import { spawn } from "child_process";
import { createLogger, debugSuppressedError } from "./logger.js";
const log = createLogger("process-tracker");
/** Internal record for a tracked child process. */type TrackedProcess = { pid: number; createdAt: number;};
/** Map of PID → TrackedProcess for all currently tracked child processes. */const tracked = new Map<number, TrackedProcess>();
/** Add a PID to the tracker. Called by tracked-bash.ts after spawning. */export function registerProcess(pid: number): void { if (!Number.isFinite(pid)) return; tracked.set(pid, { pid, createdAt: Date.now() });}
/** Remove a PID from the tracker. Called by tracked-bash.ts when a process exits. */export function unregisterProcess(pid: number): void { tracked.delete(pid);}
/** Return the list of currently tracked PIDs. Used for diagnostics. */export function listTrackedProcesses(): number[] { return [...tracked.keys()];}
/** * Kill a process and its entire process tree. * On Unix, sends SIGKILL to the process group (-pid); falls back to * killing just the PID if the group kill fails. * On Windows, uses `taskkill /F /T`. */export function killProcessTree(pid: number): void { if (!Number.isFinite(pid)) return; if (process.platform === "win32") { try { spawn("taskkill", ["/F", "/T", "/PID", String(pid)], { stdio: "ignore", detached: true, }); } catch (err) { debugSuppressedError(log, "Failed to invoke taskkill for a tracked process tree.", err, { operation: "process_tracker.kill_process_tree.taskkill", pid, }); } return; }
try { process.kill(-pid, "SIGKILL"); } catch { try { process.kill(pid, "SIGKILL"); } catch (err) { debugSuppressedError(log, "Failed to SIGKILL a tracked process after process-group termination failed.", err, { operation: "process_tracker.kill_process_tree.kill_pid", pid, }); } }}
/** * Kill all tracked processes and clear the tracker. * Returns the number of processes that were killed. * Called by agent-pool.ts on abort and runtime.ts on shutdown. */export function killTrackedProcesses(): number { const pids = [...tracked.keys()]; for (const pid of pids) { killProcessTree(pid); tracked.delete(pid); } return pids.length;}