Follow-up from #136. detached: true calls setsid(), which severs HexOps's foreground process group and session — so Ctrl-C and terminal close no longer reap managed dev servers the way they used to. #136 added a SIGINT/SIGTERM handler to replace that. It works, but its registration is fragile.
Listener accumulation
shutdownHandlersRegistered is module-scoped, so it resets on every module re-evaluation. Measured by importing the module 12 times with cache-busting specifiers:
SIGINT listeners: 12, SIGTERM listeners: 12
MaxListenersExceededWarning at 11
HexOps runs as node server.js under Next dev, where server modules are re-evaluated on edit — so this is routine, not exotic.
The stale-map winner
Worse than the warning: the first registered handler calls process.exit(130), so the oldest module instance wins — holding a stale, likely empty activeProcesses. Net effect after any HMR reload, Ctrl-C reaps nothing, silently.
Also missing: SIGHUP
Terminal close sends SIGHUP to the session. setsid() severed that too, and there is no SIGHUP handler — so closing the terminal orphans every managed server.
Suggested direction
Move registration somewhere evaluated once (or guard on a globalThis symbol rather than a module-scoped boolean), have the handler read the live map rather than a captured one, and add SIGHUP alongside SIGINT/SIGTERM.
Follow-up from #136.
detached: truecallssetsid(), which severs HexOps's foreground process group and session — so Ctrl-C and terminal close no longer reap managed dev servers the way they used to. #136 added aSIGINT/SIGTERMhandler to replace that. It works, but its registration is fragile.Listener accumulation
shutdownHandlersRegisteredis module-scoped, so it resets on every module re-evaluation. Measured by importing the module 12 times with cache-busting specifiers:HexOps runs as
node server.jsunder Next dev, where server modules are re-evaluated on edit — so this is routine, not exotic.The stale-map winner
Worse than the warning: the first registered handler calls
process.exit(130), so the oldest module instance wins — holding a stale, likely emptyactiveProcesses. Net effect after any HMR reload, Ctrl-C reaps nothing, silently.Also missing: SIGHUP
Terminal close sends SIGHUP to the session.
setsid()severed that too, and there is no SIGHUP handler — so closing the terminal orphans every managed server.Suggested direction
Move registration somewhere evaluated once (or guard on a
globalThissymbol rather than a module-scoped boolean), have the handler read the live map rather than a captured one, and add SIGHUP alongside SIGINT/SIGTERM.