Persist sessions across server restarts via per-session holders
Make dosh terminal sessions survive a dosh-server restart (crash/upgrade/systemctl restart): a reattaching client lands on the SAME shell with screen state intact, instead of a fresh one. Design: when persist_sessions is on (new config, default true) each terminal session's shell runs in a small detached per-session holder process (the dosh-server binary re-exec'd as `dosh-server hold`). The holder double-forks + setsid into its own session, opens the PTY, spawns the shell as ITS child, and serves the PTY master fd over a per-session Unix socket via SCM_RIGHTS. The server adopts that fd to build a PtyHandle that DETACHES (does not kill the shell) on drop, so a server exit leaves holder + shell alive. On startup the server scans the runtime dir under sessions_dir/run, reconnects to each live holder, receives the master fd again, restores the persisted vt100 screen, and rebuilds the Session. Screen/scrollback (server-memory only) is mirrored to disk atomically: byte-throttled on the output hot path plus a 2s periodic flush, and restored on re-adoption so reattach repaints. Truly-abandoned persistent sessions are still reaped per the existing grace logic by asking the holder to shut down. Anything in the persistent path failing degrades gracefully to the original in-process shell. PtyHandle gains an Owned (kill-on-drop, unchanged default) vs Adopted (detach-on-drop) backing; resize on an adopted master uses TIOCSWINSZ. No wire-format change, so protocol::VERSION stays 3. New deps: libc (direct). New config: persist_sessions (default true); existing integration tests pin it false to keep exercising the non-persistent path unchanged. Adds tests/integration_smoke.rs::session_survives_server_restart_same_ shell_and_screen: attaches, sets `cd /tmp; export MARK=...`, paints a screen marker, KILLs the server, restarts it on the same config, reattaches and asserts same shell pid + MARK + PWD + restored screen. Plus persist.rs unit tests (name round-trip, screen save/load, dead-holder scan cleanup, SCM_RIGHTS fd round-trip). cargo fmt --check and cargo test green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -123,8 +123,13 @@ Native v1 must be boring under real use:
|
||||
|
||||
- A closed laptop must not kill the remote session.
|
||||
- A client crash must not kill the remote session.
|
||||
- Server restart may drop live PTYs in v1 unless session persistence is implemented,
|
||||
but the client must fail clearly and reconnect cleanly afterward.
|
||||
- A server restart must not kill the remote session when `persist_sessions` is on
|
||||
(the default): each session's shell runs in a detached per-session *holder*
|
||||
process whose PTY master fd the server passes back to itself via SCM_RIGHTS, so
|
||||
the shell + scrollback survive a server crash/upgrade/`systemctl restart` and a
|
||||
reattaching client lands on the same shell with its screen restored. With
|
||||
`persist_sessions = false` the old behavior applies: live PTYs drop on restart,
|
||||
but the client must still fail clearly and reconnect cleanly afterward.
|
||||
- Decrypt failures from stale packets must be ignored or trigger reconnect, never
|
||||
terminate the terminal by themselves.
|
||||
- Terminal cleanup must restore cursor, mouse mode, bracketed paste, alternate
|
||||
|
||||
Reference in New Issue
Block a user