From e7d8220788b4fa7c266a1e4457591b694478771c Mon Sep 17 00:00:00 2001 From: Can Celik Date: Mon, 7 Sep 2026 16:14:46 +0300 Subject: fix: preserve sessions after interrupted pane exits (#3418) * fix: preserve sessions when pane shells are signaled refs #3415 * fix: preserve shutdown checkpoints across platforms refs #3415 --------- Co-authored-by: Jonathan Liebig --- src/server/headless.rs | 2 +- src/server/headless/notifications.rs | 2 +- src/server/headless/tests/mod.rs | 21 ++++++++++++++++++--- 3 files changed, 20 insertions(+), 5 deletions(-) (limited to 'src/server') diff --git a/src/server/headless.rs b/src/server/headless.rs index abaca0aa..2d652378 100644 --- a/src/server/headless.rs +++ b/src/server/headless.rs @@ -721,7 +721,7 @@ impl HeadlessServer { // Save session on exit. if self.app.policy.persist_session { - self.app.save_session_now(); + self.app.save_session_on_shutdown(); } info!("headless server exiting"); diff --git a/src/server/headless/notifications.rs b/src/server/headless/notifications.rs index dd661809..ddf9a9b3 100644 --- a/src/server/headless/notifications.rs +++ b/src/server/headless/notifications.rs @@ -663,7 +663,7 @@ impl HeadlessServer { } true } - AppEvent::PaneDied { pane_id } + AppEvent::PaneDied { pane_id, .. } | AppEvent::WorktreeRuntimeRestoreFailed { pane_id, .. } => { let focus_before = self.shell_focus_targets(); let focused_tabs_before = self.focused_shell_tabs(); diff --git a/src/server/headless/tests/mod.rs b/src/server/headless/tests/mod.rs index 5e0e5d01..63f7264d 100644 --- a/src/server/headless/tests/mod.rs +++ b/src/server/headless/tests/mod.rs @@ -3614,7 +3614,12 @@ async fn pane_death_reconciles_each_client_view_and_focus() { server.clients.get_mut(&71).unwrap().outer_terminal_focus = Some(true); server.clients.get_mut(&72).unwrap().outer_terminal_focus = Some(false); - assert!(server.handle_internal_event_with_forwarding(AppEvent::PaneDied { pane_id: dead_pane })); + assert!( + server.handle_internal_event_with_forwarding(AppEvent::PaneDied { + pane_id: dead_pane, + exit_reason: crate::platform::ChildExitReason::Exited + }) + ); assert_eq!( server.shell_tab_id_for_client(71).as_deref(), @@ -3678,7 +3683,12 @@ async fn pane_death_reapplies_controller_geometry() { let shrunk = server.app.state.workspaces[0].test_runtimes[&first_pane].current_size(); assert!(shrunk.0 < 46); - assert!(server.handle_internal_event_with_forwarding(AppEvent::PaneDied { pane_id: dead_pane })); + assert!( + server.handle_internal_event_with_forwarding(AppEvent::PaneDied { + pane_id: dead_pane, + exit_reason: crate::platform::ChildExitReason::Exited + }) + ); let runtime = &server.app.state.workspaces[0].test_runtimes[&first_pane]; let grown = runtime.current_size(); @@ -3858,7 +3868,12 @@ fn expected_worktree_runtime_exit_does_not_release_agent() { .pending_worktree_remove_runtime_exits .insert(pane_id, 1); - assert!(server.handle_internal_event_with_forwarding(AppEvent::PaneDied { pane_id })); + assert!( + server.handle_internal_event_with_forwarding(AppEvent::PaneDied { + pane_id, + exit_reason: crate::platform::ChildExitReason::Exited + }) + ); assert_eq!( server.app.state.terminals[&terminal_id].state, -- cgit v1.2.3