fix(tui): add signal handlers to prevent orphaned processes on terminal close#13848
fix(tui): add signal handlers to prevent orphaned processes on terminal close#13848Arasple wants to merge 1 commit intoanomalyco:devfrom
Conversation
…al close When a terminal tab/window is closed, the OS sends SIGHUP to the process group. @opentui/core registers handlers for SIGTERM/SIGINT/SIGQUIT/SIGABRT that call destroy() but never call process.exit() or re-raise the signal, silently swallowing them. SIGHUP has no handler at all. Combined with the Worker thread keeping the event loop alive, the bun binary survives as an orphan (PPID=1) with revoked file descriptors, leaking memory indefinitely. On a real machine this accumulated 150+ orphaned processes consuming ~13GB of RAM over 10 days. The fix registers signal handlers in thread.ts that gracefully shut down the worker (disposing instances, stopping servers) before calling process.exit() with the correct signal-based exit code (128 + signum). A 5-second timeout ensures exit even if shutdown hangs. Fixes anomalyco#12767, relates to anomalyco#11527, anomalyco#10563
|
The following comment was made by an LLM, it may be inaccurate: Potential Duplicate PRs FoundBased on the search results, here are related PRs addressing similar issues:
These PRs appear to be addressing the same root problem (orphaned processes) but in different contexts. PR #12718 seems most directly related as it handles SIGHUP signals similarly. You may want to verify whether these are complementary fixes or if any have already been merged/superseded. |
What does this PR do?
Fixes #12767, relates to #11527, #10563
When a terminal tab is closed,
@opentui/core'sexitHandlercatches SIGTERM/SIGINT/SIGQUIT/SIGABRT but only callsdestroy()without callingprocess.exit()or re-raising the signal -- silently swallowing them. SIGHUP has no handler at all. The Worker thread keeps the event loop alive, so the bun binary survives as an orphan (PPID=1) with revoked file descriptors, leaking memory indefinitely.On my machine this accumulated 152 orphaned processes over 10 days.
The fix adds signal handlers in
thread.tsthat gracefully shut down the worker (disposes instances, stops servers) before callingprocess.exit()with the correct exit code (128 + signum). A 5s timeout ensures exit even if shutdown hangs. A reentrancy guard prevents double-shutdown from multiple signals.How did you verify your code works?
tsc --noEmitpasses (0 errors inopencodepackage)kill -HUP <pid>andkill -TERM <pid>both cause clean exit^Cas a keypress)