From 76ee4ab02ba3c423860e2e73f576708ac8bed6a6 Mon Sep 17 00:00:00 2001 From: Cole Leavitt Date: Fri, 20 Feb 2026 16:39:17 -0700 Subject: [PATCH] fix: add SIGHUP/SIGTERM/SIGPIPE handlers to prevent orphaned processes When a controlling terminal is destroyed (SSH disconnect, tmux pane close), opencode processes become orphaned because the TUI event loop blocks on stdin that will never produce input, preventing process.exit() from executing. Each orphaned instance leaks ~4.7 GB of RAM. On systems using tmux-based session managers (e.g. oh-my-opencode), this can accumulate to 60+ GB. Add signal handlers for SIGHUP, SIGTERM, and SIGPIPE that call process.exit(1) immediately, ensuring clean shutdown on terminal death. Fixes #14504 --- packages/opencode/src/index.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/opencode/src/index.ts b/packages/opencode/src/index.ts index 65515658862..1c426065850 100644 --- a/packages/opencode/src/index.ts +++ b/packages/opencode/src/index.ts @@ -45,6 +45,18 @@ process.on("uncaughtException", (e) => { }) }) +// Handle terminal death signals to prevent orphaned processes. +// When a controlling terminal is destroyed (SSH disconnect, tmux pane close, etc.), +// the kernel sends SIGHUP. Without this handler, the process continues running +// indefinitely because the TUI event loop blocks on stdin that will never arrive, +// preventing the `process.exit()` in the finally block from ever executing. +// This was observed to leak ~4.7 GB per orphaned instance. +for (const sig of ["SIGHUP", "SIGTERM", "SIGPIPE"] as const) { + process.on(sig, () => { + process.exit(1) + }) +} + const cli = yargs(hideBin(process.argv)) .parserConfiguration({ "populate--": true }) .scriptName("opencode")