From 0ff0f27e222633c97ba4291f6b9be4137002ca84 Mon Sep 17 00:00:00 2001 From: Can Celik Date: Mon, 21 Sep 2026 00:29:45 +0300 Subject: fix: preserve session layouts across shutdown and restore failures (#4400) * fix: preserve session layouts across shutdown and restore failures refs #4320 * test: update subscription fixture for pane restore errors --------- Co-authored-by: JJ Liebig --- src/server/headless.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'src/server/headless.rs') diff --git a/src/server/headless.rs b/src/server/headless.rs index f07c0c37..638559ad 100644 --- a/src/server/headless.rs +++ b/src/server/headless.rs @@ -250,6 +250,7 @@ pub struct HeadlessServer { pending_handoff_repaint_nudge: bool, /// Flag set by Ctrl+C or `server stop` signal. should_quit: Arc, + host_shutdown_requested: Arc, /// Channel for receiving server events from client connection threads. server_event_rx: mpsc::Receiver, /// Sender for server events (cloned for each client thread). @@ -373,6 +374,7 @@ impl HeadlessServer { headless_size, effective_size: headless_size, shutting_down: false, + host_shutdown_requested: Arc::new(AtomicBool::new(false)), handoff_in_progress: false, #[cfg(unix)] pending_handoff_repaint_nudge: false, @@ -398,6 +400,13 @@ impl HeadlessServer { let should_quit = self.should_quit.clone(); let quit_notify = self.server_event_tx.clone(); ctrlc_handler(should_quit, quit_notify); + let quit_notify = self.server_event_tx.clone(); + let _host_shutdown = crate::platform::HostShutdownMonitor::start( + self.host_shutdown_requested.clone(), + move || { + let _ = quit_notify.try_send(ServerEvent::QuitSignal); + }, + ); let mut needs_render = true; let mut needs_full_render = true; @@ -414,6 +423,13 @@ impl HeadlessServer { break; } + // A host shutdown warning precedes process termination. Do not drain pane + // deaths here: logind's delay lock stays held until the final session save. + if self.host_shutdown_requested.load(Ordering::Acquire) { + self.initiate_shutdown(); + continue; + } + // Check if we should start shutting down. if self.app.state.should_quit || self.should_quit.load(Ordering::Acquire) { self.drain_internal_events_with_forwarding_up_to( @@ -638,7 +654,9 @@ impl HeadlessServer { } }; - if self.should_quit.load(Ordering::Acquire) { + if self.should_quit.load(Ordering::Acquire) + || self.host_shutdown_requested.load(Ordering::Acquire) + { match event { LoopEvent::Internal(ev) => { self.handle_internal_event_with_forwarding(ev); -- cgit v1.2.3