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.
This commit is contained in:
Thomas Eizinger
2025-02-10 03:33:24 +00:00
committed by GitHub
parent 36f5eee99d
commit fdb7631529
4 changed files with 14 additions and 10 deletions

View File

@@ -577,10 +577,15 @@ impl<I: GuiIntegration> 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 {

View File

@@ -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(),
}
}

View File

@@ -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.

View File

@@ -27,7 +27,12 @@ export default function GUI({ title }: { title: string }) {
return (
<Entries downloadLinks={downloadLinks} title={title}>
{/* 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. */}
<Unreleased></Unreleased>
<Unreleased>
<ChangeItem pull="8035">
Shows a non-disruptive toast notification and quits the GUI client in
case the IPC service gets shutdown through the service manager.
</ChangeItem>
</Unreleased>
<Entry version="1.4.3" date={new Date("2025-02-05")}>
{title == "Linux GUI" && (
<ChangeItem>