Preserve restored screen during ticket reattach
ci / test (push) Waiting to run
ci / fuzz-smoke (push) Waiting to run
ci / windows-client (push) Waiting to run
ci / package-release (linux-x86_64, ubuntu-latest) (push) Waiting to run
ci / package-release (macos-aarch64, macos-14) (push) Waiting to run
ci / package-release (macos-x86_64, macos-13) (push) Waiting to run
ci / package-release (windows-x86_64, windows-latest) (push) Waiting to run
ci / publish-gitea-release (push) Blocked by required conditions
ci / remote-bench (push) Waiting to run

This commit is contained in:
DuProcess
2026-07-12 22:54:39 -04:00
parent 6bca98d1ce
commit 52a319fe9d
3 changed files with 68 additions and 2 deletions
+23 -2
View File
@@ -813,6 +813,10 @@ fn attach_snapshot(session: &Session, cols: u16, rows: u16) -> Vec<u8> {
screen_snapshot(session.parser.screen())
}
fn restored_screen_is_pending_reattach(session: &Session) -> bool {
session.restored_screen.is_some()
}
fn mode_allows_terminal_updates(mode: &str) -> bool {
mode != "view-only" && mode != "forward-only"
}
@@ -3707,7 +3711,7 @@ async fn broadcast_output(
// short wall-clock age so low-throughput prompt/TUI changes persist
// quickly while large bursts still avoid per-packet disk writes. The
// actual file write happens after the lock is dropped.
if session.persistent {
if session.persistent && !restored_screen_is_pending_reattach(session) {
session.bytes_since_persist = session
.bytes_since_persist
.saturating_add(output.bytes.len());
@@ -4060,7 +4064,10 @@ fn flush_persistent_screens(state: &Arc<Mutex<ServerState>>) {
let sessions_dir = locked.sessions_dir();
let mut to_write: Vec<(String, u16, u16, u64, Vec<u8>)> = Vec::new();
for (name, session) in locked.sessions.iter_mut() {
if !session.persistent || session.output_seq == session.last_persisted_seq {
if !session.persistent
|| restored_screen_is_pending_reattach(session)
|| session.output_seq == session.last_persisted_seq
{
continue;
}
session.bytes_since_persist = 0;
@@ -4411,6 +4418,20 @@ mod tests {
let session = locked.sessions.get("work").unwrap();
assert!(session.restored_screen.is_some());
assert_eq!(attach_snapshot(session, 80, 24), restored);
assert_eq!(
session.last_persisted_seq, 7,
"pre-reattach PTY output must not overwrite the persisted restored screen"
);
drop(locked);
flush_persistent_screens(&state);
let locked = state.lock().unwrap();
let session = locked.sessions.get("work").unwrap();
assert_eq!(
session.last_persisted_seq, 7,
"periodic flush must not replace restored screen before client-visible output"
);
}
#[test]