From fdb7631529b30a5de7e530d15513f0a363e64fa9 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Mon, 10 Feb 2025 03:33:24 +0000 Subject: [PATCH] feat(gui-client): gracefully exit GUI on graceful IPC shutdown (#8035) When the IPC service gets terminated gracefully, the user must have initiated some kind of action, be it an upgrade or an explicit "Stop the service". In that case, there is no point in displaying an alert with an info / error message as the user already knows that they are stopping Firezone. In order to not fatigue the user with alerts, we exit the GUI with a toast notification when the IPC service shuts down gracefully. Toast notifications do not grab the users attention, allowing them to continue what they are doing while still being notified that their Firezone client is now disconnected. Fixes: #6232. --- rust/gui-client/src-common/src/controller.rs | 9 +++++++-- rust/gui-client/src-common/src/errors.rs | 6 ------ rust/gui-client/src-tauri/src/client/gui.rs | 2 +- website/src/components/Changelog/GUI.tsx | 7 ++++++- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/rust/gui-client/src-common/src/controller.rs b/rust/gui-client/src-common/src/controller.rs index 9c15882e7..dac5ca773 100644 --- a/rust/gui-client/src-common/src/controller.rs +++ b/rust/gui-client/src-common/src/controller.rs @@ -577,10 +577,15 @@ impl Controller<'_, I> { self.update_disabled_resources().await?; } IpcServerMsg::TerminatingGracefully => { - tracing::info!("Caught TerminatingGracefully"); + tracing::info!("IPC service exited gracefully"); self.integration .set_tray_icon(system_tray::icon_terminating()); - Err(Error::IpcServiceTerminating)? + self.integration.show_notification( + "Firezone disconnected", + "The Firezone IPC service was shutdown, quitting GUI process.", + )?; + + return Ok(ControlFlow::Break(())); } IpcServerMsg::TunnelReady => { let Status::WaitingForTunnel { start_instant } = self.status else { diff --git a/rust/gui-client/src-common/src/errors.rs b/rust/gui-client/src-common/src/errors.rs index 2511d5d2a..788c43551 100644 --- a/rust/gui-client/src-common/src/errors.rs +++ b/rust/gui-client/src-common/src/errors.rs @@ -10,8 +10,6 @@ pub enum Error { IpcClosed, #[error("IPC read failed")] IpcRead(#[source] anyhow::Error), - #[error("IPC service terminating")] - IpcServiceTerminating, #[error(transparent)] Other(#[from] anyhow::Error), } @@ -36,10 +34,6 @@ impl Error { } Error::IpcClosed => "IPC connection closed".to_string(), Error::IpcRead(_) => "IPC read failure".to_string(), - Error::IpcServiceTerminating => { - "The Firezone IPC service is terminating. Please restart the GUI Client." - .to_string() - } Error::Other(error) => error.to_string(), } } diff --git a/rust/gui-client/src-tauri/src/client/gui.rs b/rust/gui-client/src-tauri/src/client/gui.rs index 60090d55e..cf48fb528 100644 --- a/rust/gui-client/src-tauri/src/client/gui.rs +++ b/rust/gui-client/src-tauri/src/client/gui.rs @@ -278,7 +278,7 @@ pub(crate) fn run( // But due to a limit in `tao` we cannot return from the event loop and must call `std::process::exit` (or Tauri's wrapper), so we explicitly flush here. // TODO: This limit may not exist in Tauri v2 - tracing::info!(?exit_code); + tracing::info!(%exit_code, "Goodbye!"); app_handle.exit(exit_code); // In Tauri v1, calling `App::exit` internally exited the process. // In Tauri v2, that doesn't happen, but `App::run` still doesn't return, so we have to bail out of the process manually. diff --git a/website/src/components/Changelog/GUI.tsx b/website/src/components/Changelog/GUI.tsx index a124e67e8..ee4001b93 100644 --- a/website/src/components/Changelog/GUI.tsx +++ b/website/src/components/Changelog/GUI.tsx @@ -27,7 +27,12 @@ export default function GUI({ title }: { title: string }) { return ( {/* When you cut a release, remove any solved issues from the "known issues" lists over in `client-apps`. This must not be done when the issue's PR merges. */} - + + + Shows a non-disruptive toast notification and quits the GUI client in + case the IPC service gets shutdown through the service manager. + + {title == "Linux GUI" && (