UNPKG

claude-flow

Version:

Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration

70 lines 2.4 kB
/** * Parent-death watchdog (#2234). * * `ruflo mcp start` runs as a double-forked grandchild of Claude Code (`npx -y * ruflo … mcp start` → `npm exec …` → `node … mcp start`). When Claude Code * exits, only the `npm exec` shim is terminated; the `node` server reparents to * `launchd`/`init` (`ppid === 1`) and silently lingers — leaving ~50 MB and an * open database handle per restart. Over a week this accumulates to ~20 * orphaned servers (~1 GB), and an arbitrary stale one can win the next stdio * handshake, transparently serving superseded code. * * Cheap, robust fix: poll `process.ppid`. When it becomes 1 (and didn't start * there), our original parent has exited — we're orphaned. Run the cleanup * hook and exit cleanly. * * @module runtime/parent-death-watchdog */ /** * Install a parent-death watchdog. Safe to call once per process; calling * twice replaces the previous interval. */ export function installParentDeathWatchdog(opts = {}) { const intervalMs = opts.intervalMs ?? 2000; const get = opts.ppidGetter ?? (() => process.ppid); const exit = opts.exit ?? ((code) => process.exit(code)); const onOrphaned = opts.onOrphaned; const initialPpid = get(); let triggered = false; let timer; const triggerOrphaned = async () => { if (triggered) return; triggered = true; if (timer) { clearInterval(timer); timer = undefined; } try { if (onOrphaned) await onOrphaned(); exit(0); } catch { exit(1); } }; const checkOnce = async () => { // Only trigger when we *transition* to ppid=1; if we already started there // (process launched directly under launchd/init) it isn't an orphan event. const ppid = get(); if (ppid === 1 && initialPpid !== 1) await triggerOrphaned(); }; timer = setInterval(() => { void checkOnce(); }, intervalMs); // Don't keep the event loop alive on the watchdog alone. if (typeof timer.unref === 'function') timer.unref(); return { stop() { if (timer) { clearInterval(timer); timer = undefined; } }, checkOnce, }; } //# sourceMappingURL=parent-death-watchdog.js.map