Files
Jesse Vincent ea0a29e230 fix(mcp-server): kill orphaned npm install children and prevent install pile-up (#161)
mcp-server-wrapper.js ran `npm install` during the MCP handshake with no
signal handlers registered — a client-side connect-timeout kill left the
install running as an orphan, and repeated wrapper launches stacked
unbounded concurrent installs (#161 observed 5).

Factor spawn+lock+cleanup into cli/install-runner.js:
- runNpmInstall() tracks the spawned child and registers
  process.on('exit'|SIGTERM|SIGINT|SIGHUP) handlers for the duration of the
  install, removing them once the child exits. On POSIX the child is
  spawned detached so termination can process.kill(-pid, signal) the whole
  process group (npm's node-gyp grandchildren included), falling back to
  child.kill() if the group kill fails; Windows uses child.kill() only,
  since it can't kill by negative pid.
- acquireInstallLock()/releaseInstallLock() are a built-in-fs-only
  (atomic mkdirSync, EEXIST = held, mtime-based stale steal) exclusive lock
  in the plugin dir, deliberately not using proper-lockfile since that
  package is itself one of the things the guarded install is supposed to
  provide. A second wrapper invocation that sees the lock held waits
  (waitForInstallLock, bounded poll) instead of starting a competing
  install, then re-probes findMissingDeps before continuing.

Claude-Session: https://claude.ai/code/session_0112vdwZphiWzfCYfaXMes4C
2026-09-08 19:45:58 +00:00
..