fix(ui): exit when the terminal hosting a review disconnects - #724
fix(ui): exit when the terminal hosting a review disconnects#724NiqhtFire wants to merge 8 commits into
Conversation
|
PR author is not in the allowed authors list. |
|
@NiqhtFire is attempting to deploy a commit to the Modem Team on Vercel. A member of the Team first needs to authorize it. |
|
Please merge this fix. |
|
Thanks for the thorough investigation here—the SIGHUP and PTY disconnect handling looks solid. I found one blocker: OpenTUI also intercepts signals such as Could we disable OpenTUI’s signal ownership with Two smaller test notes:
This comment was generated by Pi using gpt-5.6-sol |
|
Thanks, I disabled OpenTUI’s signal handling and moved clean shutdowns into Hunk itself, including SIGQUIT and SIGPIPE. Tests now cover those signals, assert exit code 0, and verify non-TTY rendering doesn’t exit early. |
Problem
Hunk can keep running after the terminal hosting a review disappears, leaving behind a process that can no longer be reached.
I reproduced this in three cases:
SIGHUPwith session brokering enabled (the default), the renderer shuts down but the process stays alive indefinitely.Why this happens
The
SIGHUPbehavior comes from anomalyco/opentui#1355. OpenTUI'sCliRendererinstalls listeners for its defaultexitSignals, includingSIGHUP. Its shared handler callsdestroy(), but does not exit the process or restore the signal's default termination behavior. The process therefore exits only if nothing else is keeping the event loop alive.Hunk's session broker client keeps the event loop alive, which is why the problem appears with the default configuration:
kill -HUPHUNK_MCP_DISABLE=1)The pinned
@opentui/core@0.4.3uses the sameexitHandlerdescribed in the issue. HandlingSIGHUPin Hunk is the recommended workaround and can be removed once OpenTUI fixes the behavior upstream.The upstream issue reports an orphaned process using roughly 100% CPU. However, Hunk behaves differently: after
SIGHUP, the orphaned process idles at around 0.1–0.4% CPU, with a ~1s spike when the TTY is revoked. The main problem here is the stranded process not the CPU usage.What changed
close,end, orerror.SIGHUP.The TTY guard matters because non-terminal stdin, such as a pipe or
/dev/null, ends as soon as the renderer resumes it. Without the guard,hunk diff a b < /dev/nullexits successfully without rendering anything.test/cli/non-interactive-stdin.test.tsis written for this case.OpenTUI already replaces the default
SIGHUPbehavior, so adding Hunk's listener does not change the signal.Tests
test/pty/lifecycle.test.tscovers all three ways the terminal can go away. The macOS case usesrevoke(2), which is not available on Linux. For the cross-platform PTY master-close case, the test allocates a PTY withbun:ffiandopenpty, then starts Hunk on the slave withnode:child_process. This is needed since tuistory/node-pty kills the child during teardown and cannot model a host closing the master while the child keeps the slave.The
SIGHUPcase runs with brokering enabled, since disabling it removes the pending handle and the test would pass for the wrong reason.Known unrelated failures
There are some test failures that can also be reproduce on
61cc6b1(latest main branch by the time this pr is created) without this branch when runningbun run testandbun run test:integration