fix(minimald,minimal): keepalives instead of the inactivity reaper - #798
Conversation
russh's default server config ships a 600s inactivity_timeout that garbage-collects any connection with no inbound traffic — including a healthy attached session whose user simply stops typing for ten minutes. When the resulting close was lost across the vsock, the client (which defaults to no keepalives and no timeout of its own) hung forever: the "established attach died silently" field report, reproduced on demand from nothing but idle time. Invert the liveness policy on both sides: probe quiet connections every 20s, tolerate 3 unanswered probes (~60s bounded detection of dead peers, visible as an error), and switch the wall-clock reaper off explicitly — an idle connection is not a dead one. Binding teardown when a connection dies out from under it is handled separately. Refs: #788 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe server now uses explicit SSH keepalive settings instead of inactivity reaping defaults. The client documents its intentional absence of keepalives, and the Linux KVM build timeout is increased. ChangesSSH keepalive behavior
CI build timeout
Estimated code review effort: 2 (Simple) | ~10 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Comment |
twitchyliquid64
left a comment
There was a problem hiding this comment.
I suggest:
- keepalive interval in the 10 mins to 1 hr range
- No client keepalives, or have them be in the 10mins or more range
The 20s keepalive interval was too aggressive: it wakes the radio every 20s, draining the battery — a real cost once these connections run remote. And the client keepalive broke the "close the laptop for an hour, reopen, still works" case, which works precisely when the client does not send keepalives. With the wall-clock inactivity reaper already off, keepalives only need to be a slow liveness backstop, not fast-detection: no idle-but-alive session is ever spuriously reaped, so we do not need to notice a dead peer quickly. So: - minimald: KEEPALIVE_INTERVAL 20s -> 30min (KEEPALIVE_MAX stays 3). ~30min x 3 ~= 90min to reap a truly-dead peer, which is fine. - minimal: drop client keepalives entirely; back to russh::client::Config::default(). A laptop closed for an hour now reconnects transparently on wake, and the server's long-interval keepalive is the only liveness mechanism. Refs: #788 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
6d666a7 to
dd08d8b
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/minimal/src/client.rs`:
- Around line 84-88: Reword the comment describing the client’s keepalive
behavior to avoid promising transparent or automatic reconnection. Clarify that
this layer maintains a single SSH session and disabling client keepalives only
prevents client-side timeout during sleep; state that higher layers must
recreate the session after wake if recovery is needed.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3b85e3c1-653d-4446-9541-80dcffa7bf8d
📒 Files selected for processing (2)
crates/minimal/src/client.rscrates/minimald/src/server.rs
A cold cargo build takes just over 45 minutes, so once the cache entry is evicted the job times out before its main-only save step can run and the cache never repopulates — every subsequent run on main and on PRs builds cold and times out again. 60 minutes lets a cold build finish. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Summary
Fixes the reproduced mechanism behind #788: russh's inherited
inactivity_timeout: Some(600s)reaps healthy-but-quiet attaches; a lost close across the vsock (#588) then leaves the client — no keepalives, no timeout — hung forever. Full evidence chain and on-demand reproduction in the issue thread.inactivity_timeout: None(explicit),keepalive_interval: 20s,keepalive_max: 3, with named constants documenting the policyOut of scope (tracked in #788): binding teardown on connection death (owned separately), bounded
attach()for the establishment race, #588 upstream.Test plan
cargo check -p minimal(macOS) — client config compilesRefs: #788
🤖 Generated with Claude Code
Summary by CodeRabbit