diff options
| author | Can Celik <ogulcancelik@gmail.com> | 2026-08-15 15:03:59 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-08-15 15:03:59 +0300 |
| commit | b660cad80450147610091e0e5758faa6276e5983 (patch) | |
| tree | 5896dce7455f69199447520c19a40af5472e436a /src/client | |
| parent | 9e6c2b4e0957498b7da884ed2789fe28b9cde9cf (diff) | |
fix(client): handle remote terminal hangup (#2827)
refs #2424
Diffstat (limited to 'src/client')
| -rw-r--r-- | src/client/mod.rs | 46 |
1 files changed, 34 insertions, 12 deletions
diff --git a/src/client/mod.rs b/src/client/mod.rs index cba735fa..b70b6c9c 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -421,6 +421,7 @@ fn setup_terminal_with_capabilities( Ok(TerminalGuard { reset_modify_other_keys: modify_other_keys_mode.is_some(), reset_host_color_scheme_reports: host_color_scheme_reports, + restored: false, #[cfg(windows)] restore_windows_input_mode: windows_virtual_terminal_input.restore_mode, }) @@ -434,6 +435,7 @@ fn should_enable_host_color_scheme_reports(enable_client_protocols: bool) -> boo struct TerminalGuard { reset_modify_other_keys: bool, reset_host_color_scheme_reports: bool, + restored: bool, #[cfg(windows)] restore_windows_input_mode: Option<u32>, } @@ -582,7 +584,7 @@ fn restore_terminal_state( reset_modify_other_keys: bool, reset_host_color_scheme_reports: bool, #[cfg(windows)] restore_windows_input_mode: Option<u32>, -) { +) -> io::Result<()> { let _ = clear_received_kitty_graphics(&mut io::stdout()); // Reset modifyOtherKeys if we enabled it. @@ -606,13 +608,16 @@ fn restore_terminal_state( restore_windows_input_mode_value(mode); } - let _ = ratatui::try_restore(); - let _ = write_terminal_restore_postlude(&mut io::stdout(), reset_host_color_scheme_reports); + let restore_result = ratatui::try_restore(); + let postlude_result = + write_terminal_restore_postlude(&mut io::stdout(), reset_host_color_scheme_reports); #[cfg(windows)] if windows_vti_input_backend_enabled() && windows_win32_input_mode_enabled() { let _ = disable_windows_win32_input_mode(&mut io::stdout()); } + + restore_result.and(postlude_result) } #[cfg(not(windows))] @@ -657,14 +662,28 @@ fn disable_windows_win32_input_mode(writer: &mut impl std::io::Write) -> io::Res writer.flush() } -impl Drop for TerminalGuard { - fn drop(&mut self) { +impl TerminalGuard { + fn restore(mut self) -> io::Result<()> { + self.restored = true; restore_terminal_state( self.reset_modify_other_keys, self.reset_host_color_scheme_reports, #[cfg(windows)] self.restore_windows_input_mode, - ); + ) + } +} + +impl Drop for TerminalGuard { + fn drop(&mut self) { + if !self.restored { + let _ = restore_terminal_state( + self.reset_modify_other_keys, + self.reset_host_color_scheme_reports, + #[cfg(windows)] + self.restore_windows_input_mode, + ); + } } } @@ -1281,7 +1300,7 @@ fn run_client_with_mode( let panic_restore_windows_input_mode = terminal_guard.restore_windows_input_mode; let original_hook = std::panic::take_hook(); std::panic::set_hook(Box::new(move |info| { - restore_terminal_state( + let _ = restore_terminal_state( panic_resets_modify_other_keys, panic_resets_host_color_scheme_reports, #[cfg(windows)] @@ -1323,19 +1342,22 @@ fn run_client_with_mode( }); // Restore the terminal before printing any final status message. - drop(terminal_guard); + let terminal_restore_failed = terminal_guard.restore().is_err(); if let Err(err) = result { - eprintln!("herdr: {err}"); + let _ = writeln!(io::stderr(), "herdr: {err}"); rt.shutdown_timeout(Duration::from_millis(100)); crate::logging::shutdown("client"); - if matches!( - err, + let detached = matches!( + &err, ClientError::ServerShutdown { reason: Some(reason) } if reason == "detached" - ) { + ); + let connection_lost_during_terminal_hangup = + terminal_restore_failed && matches!(&err, ClientError::ConnectionLost(_)); + if detached || connection_lost_during_terminal_hangup { return Ok(()); } |
