mirror of
https://github.com/obra/episodic-memory.git
synced 2026-09-14 13:43:14 +08:00
ea0a29e230
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