Repository navigation
Fix stale SSH PTY resize: retry pty_resize delivery with bounded backoff - #6821
austinywang wants to merge 10 commits into
Conversation
…ivery Covers #6306. SSH workspace TUI panes can keep a stale size when a workspace.remote.pty_resize delivery fails (e.g. it races a stale/blocked remote-session control path and the bounded RPC times out). The attach helper records the pending size on failure but never re-attempts delivery on its own — it only retries on the next SIGWINCH or input edge — so the remote PTY/TUI stays frozen until a manual workspace reconnect. The test drives a single forced resize (the attach-time reconcile) whose first delivery the mock daemon rejects, then asserts the helper re-delivers the same size automatically with no further SIGWINCH or input. This fails today: with no self-driven retry, the second delivery never arrives. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fixes #6306. `cmux ssh-pty-attach` forwards SIGWINCH/input-edge size changes to the remote PTY via `workspace.remote.pty_resize` over a bounded (50ms) RPC. When that send failed — e.g. it raced a stale or blocked remote-session control path and timed out — `drainPendingResizes` recorded the pending size and returned, resuming input waiters but scheduling no further delivery. The size was only re-attempted on the *next* SIGWINCH or input edge, so a settled TUI pane could keep a stale size indefinitely. Output kept flowing, so the terminal looked alive, but the remote PTY/TUI never reconciled until a manual Reconnect Workspace rebuilt the session path. Add a self-driven retry: on delivery failure the monitor keeps the latest desired size pending (input waiters still resume immediately, so typing is never blocked behind a wedged resize) and schedules a backoff retry (100ms doubling to a 2s cap) that re-drains the pending size without waiting for an external event. The backoff resets on the first successful send, and the retry task is cancelled on teardown — so retries are bounded by the attach connection's lifetime (the output read loop cancels the monitor on bridge EOF). This keeps the scope to the "coalesced retry around the resize send" the issue calls for; the heavier remote-session reconnect path is intentionally left out. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 47 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (2)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This comment has been minimized.
This comment has been minimized.
The new regression test grew cmuxTests/CLISSHPTYResizeInputTests.swift past its
recorded 560-line ceiling. Regenerated the budget with
`python3 scripts/swift_file_length_budget.py --write-budget` (the canonical
path; the TSV is never hand-edited). The same run also tightens a few unrelated
entries down to current actual sizes, which is exactly what the budget header
asks for ("Reduce counts as files shrink").
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
….sleep Aziz concurrency policy disallows runtime `Task.sleep` (allowed in tests only; runtime waits need real signals, callbacks, or state changes). Schedule the backoff retry with a cancellable `DispatchWorkItem` via `asyncAfter` — the same one-shot timer-callback idiom the CLI already uses for the websocket keepalive — and hop back onto the actor from the callback. Behavior is unchanged: one pending retry at a time, cancelled on teardown, backoff reset on success. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ace-tui-resize-can-remain # Conflicts: # .github/swift-file-length-budget.tsv
…ace-tui-resize-can-remain # Conflicts: # .github/swift-file-length-budget.tsv
…ace-tui-resize-can-remain
…ace-tui-resize-can-remain
…ace-tui-resize-can-remain
…ace-tui-resize-can-remain
Fixes #6306.
Problem
In SSH workspaces, a terminal TUI pane could keep a stale resize state: after a pane-width change the remote TUI no longer reconciled to the visible size, and only Reconnect Workspace restored the self-healing behavior.
cmux refresh-surfacesdid not reliably repair it.cmux ssh-pty-attachforwards size changes to the remote PTY viaworkspace.remote.pty_resizeover a bounded 50 ms RPC (SSHPTYResizeMonitor). When that send failed — e.g. it raced a stale or blocked remote-session control path and the bounded RPC timed out —drainPendingResizesrecorded the pending size, resumed input waiters, and returned without scheduling any further delivery. The size was only re-attempted on the next SIGWINCH or input edge, so a settled pane (a TUI the user is just viewing) could keep a stale size indefinitely. Output kept flowing, so the terminal looked alive, but the remote PTY/TUI never reconciled until a manual reconnect rebuilt the session path — exactly the report in the issue.Fix
Make resize delivery self-healing in
CLI/SSHPTYResizeMonitor.swift:This matches the issue's "small first fix … add coalesced retry around the resize send." The heavier "trigger a remote-session reconnect / PTY reattach after repeated failures" path is intentionally out of scope — it's riskier (can disrupt the live session) and the bounded-backoff retry already lets the common transient-failure case converge on its own.
Test
Two-commit red/green. The regression test (added to the already-wired
CLISSHPTYResizeInputTestssuite) runs the realssh-pty-attachCLI against a mock daemon + bridge. It opens the PTY at the target size so the attach-time reconcile is the single forced resize, makes the daemon reject the firstpty_resize, and asserts the helper re-delivers the same size automatically with no further SIGWINCH or input edge.Localization
No user-facing strings added or changed (CLI internal control path only); no
Localizable.xcstrings/ web message updates required.🤖 Generated with Claude Code
Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.Summary by cubic
Adds a bounded backoff retry for SSH PTY resize delivery so TUI panes don’t stick at a stale size in SSH workspaces. Fixes #6306 and removes the need to reconnect after a resize RPC timeout.
Bug Fixes
CI
Written for commit 105ab95. Summary will update on new commits.