-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Problem / Background
When users run long-running interactive sessions (such as tmux) via bssh's interactive mode, the connection silently drops after a period of inactivity. This is not a tmux issue — it is caused by two bugs in bssh's interactive mode implementation:
- Interactive mode ignores keepalive configuration — CLI options and SSH config file settings are not passed through.
- PTY session has no idle detection or health check mechanism — a dead connection causes the terminal to freeze indefinitely.
Root Cause Analysis
Root Cause 1: Interactive mode ignores keepalive configuration
The CLI options --server-alive-interval and --server-alive-count-max work correctly in exec mode but are completely ignored in interactive mode.
- In exec mode (
src/app/dispatcher.rs:461-467),SshConnectionConfigis properly built with keepalive settings and passed viaClient::connect_with_ssh_config(). - In interactive mode (
src/commands/interactive/connection.rs:64), the code uses plainClient::connect()which does not acceptSshConnectionConfig, so keepalive is hardcoded to defaults (60s interval, 3 max). - The
InteractiveCommandstruct insrc/commands/interactive/types.rsdoes not have anssh_connection_configfield at all. - SSH config file (
~/.ssh/config) settings forServerAliveIntervalandServerAliveCountMaxare also ignored in interactive mode.
Root Cause 2: PTY session has no idle detection or health check
The PTY session main loop in src/pty/session/session_manager.rs:305 uses tokio::select! with three branches:
channel.wait()— waits for remote datamsg_rx.recv()— waits for local inputcancel_rx.changed()— waits for termination signal
There is no timeout branch and no periodic health check. When the SSH connection silently dies (e.g., firewall drops an idle connection), channel.wait() blocks forever and the terminal appears frozen to the user.
Disconnection scenario
- User connects via bssh interactive mode and runs tmux
- User is idle for some time
- Default keepalive: 60s interval x 3 max = 180s detection window
- If network/firewall idle timeout is shorter, or russh keepalive packets are not properly delivered, connection drops
- PTY session cannot detect the dead connection and hangs indefinitely on
channel.wait()
Keepalive support comparison
| Feature | Exec Mode | Interactive Mode |
|---|---|---|
| Keepalive applied | Yes | No (hardcoded 60s default) |
| CLI options honored | Yes | No (ignored) |
| SSH config honored | Yes | No (ignored) |
| Idle detection | Limited | None |
| Connection health check | None | None |
Proposed Solution
Fix 1: Pass SshConnectionConfig to interactive mode connections
- Add
ssh_connection_configfield toInteractiveCommandstruct (src/commands/interactive/types.rs) - Change
src/commands/interactive/connection.rs:64to useClient::connect_with_ssh_config()instead ofClient::connect() - Build keepalive config in dispatcher for interactive mode the same way as exec mode (
src/app/dispatcher.rs)
Fix 2: Add health check timer to PTY session loop
- Add a periodic timeout branch in the
tokio::select!loop insrc/pty/session/session_manager.rs:305 - Detect dead connections and notify the user instead of freezing
- Consider implementing a reconnection or graceful termination mechanism
Fix 3: Propagate keepalive settings to jump host connections in interactive mode
- Interactive mode also does not pass
SshConnectionConfigtoJumpHostChain, so jump host connections in interactive mode use hardcoded defaults too
Acceptance Criteria
-
InteractiveCommandstruct includesssh_connection_configfield - Interactive mode connections use
Client::connect_with_ssh_config()with user-specified keepalive settings - CLI options
--server-alive-intervaland--server-alive-count-maxare honored in interactive mode - SSH config file settings (
ServerAliveInterval,ServerAliveCountMax) are honored in interactive mode - PTY session loop includes a periodic health check / timeout branch
- Dead connections are detected and reported to the user instead of silently freezing
- Jump host connections in interactive mode also receive keepalive configuration
- Existing exec mode behavior remains unchanged (regression test)
Affected Files
src/commands/interactive/connection.rs— connection establishmentsrc/commands/interactive/types.rs—InteractiveCommandstructsrc/app/dispatcher.rs— config building for interactive modesrc/pty/session/session_manager.rs— PTY session loopsrc/ssh/tokio_client/connection.rs—SshConnectionConfig
Additional Context
This is a bug that affects all users of interactive mode with long-running sessions. The current workaround is limited — users cannot adjust keepalive settings to match their network environment when using interactive mode.