fix: stop terminal resize loop on dead shell session#2095
Conversation
When a shell pty exits, TerminalManager.handleExit only emitted an "exit" event — it never reset instance.isReady or disconnected the ResizeObserver. The instance is kept around so the buffer remains viewable, but the next layout shift caused the ResizeObserver to fire shell.resize against a session the main process had already discarded. That call rejects, the catch logs, the failed call updates layout, and the observer fires again. Tight enough to wedge the renderer when the tab stays attached after a setup script finishes. Set isReady to false and disconnect the ResizeObserver in handleExit so no further resize calls go out for the dead session. The instance itself is still kept until destroy() so the terminal buffer remains visible. Generated-By: PostHog Code Task-Id: 39eb3a58-c962-49af-a1ed-2c621ba04d6e
|
Reviews (1): Last reviewed commit: "fix: stop terminal resize loop on dead s..." | Re-trigger Greptile |
pauldambra
left a comment
There was a problem hiding this comment.
Note
🤖 Automated comment by QA Swarm — not written by a human
Multi-perspective review by qa-team (frontend + reliability + 2 generalists), paul-reviewer, xp-reviewer. See inline comments and the summary comment below.
|
Note 🤖 Automated comment by QA Swarm — not written by a human Multi-perspective review: qa-team (frontend + reliability + 2 generalists), paul-reviewer, xp-reviewer Verdict: 💬 APPROVE WITH NITSThe fix is correct and well-described. The diagnosis is exemplary — the commit message walks the next maintainer through the feedback loop precisely, and the diff does what it claims. No CRITICAL/HIGH findings were surfaced. The MEDIUM items are about hardening (extract a helper, lock the fix in with a test, future-proof a flag overload) and a pre-existing race that this PR doesn't introduce or worsen. Key findings🟡 MEDIUM
🟢 LOW
⚪ NIT / out-of-scope observations (rolled up here rather than inline)
Convergence
Reviewer summaries
Automated by QA Swarm — not a human review |
Three call sites in TerminalManager were repeating the same observer disconnect dance: attach(), detach(), and the new handleExit() block from the prior commit. Extract a private disconnectResizeObserver helper and call it from all three. Behaviour is unchanged. Motivated by qa-swarm feedback (3 reviewers converged on this dedup). Generated-By: PostHog Code Task-Id: c406af31-2216-42c6-a282-7fd75721a14d
Problem
The renderer would freeze when a task tab containing a finished
action-setup-*shell stayed open. Symptoms in the renderer logs:The pattern: setup script finishes, the pty is gone on the main side, but the renderer keeps the
TerminalInstancearound so its scrollback buffer remains visible.TerminalManager.handleExitonly emitted an"exit"event — it never resetinstance.isReadyor disconnected theResizeObserverset up inattach(). The observer's callback only guards oninstance.isReady, so every layout shift firestrpcClient.shell.resizeagainst the dead session, the call rejects, the catch logs, the failed call mutates layout, and the observer fires again. Tight enough to wedge the renderer.Changes
In
TerminalManager.handleExit:instance.isReady = falseso the resize guard short-circuitsResizeObserverand null it outThe instance itself is still kept until
destroy()so the buffer stays visible.How did you test this?
Terminal.tsxinvokesterminalManager.handleExitfrom theshell.onExittRPC subscription, which is exactly when the main process emits the exit. After this fix, the renderer-side state for that session is consistent with the main side.attach()for re-mount: if the user re-runs the setup,initializeSessionwill setisReady = trueagain andattach()creates a freshResizeObserver, so resizing still works.Publish to changelog?
no
🤖 Agent context
Diagnosed from a renderer log dump showing tight repetition of
Failed to resize shell: Shell session ... not foundfor anaction-setup-*session id. Cross-referencedhandleExit(noisReadyreset, no observer disconnect) with theattach()ResizeObservercallback (only guards oninstance.isReady). The fix was scoped to the smallest change that breaks the feedback loop without altering buffer-retention behavior.Created with PostHog Code