diff --git a/rust/windows-client/src-tauri/src/client/gui.rs b/rust/windows-client/src-tauri/src/client/gui.rs index 176a03382..9f323a147 100644 --- a/rust/windows-client/src-tauri/src/client/gui.rs +++ b/rust/windows-client/src-tauri/src/client/gui.rs @@ -32,6 +32,9 @@ pub(crate) fn app_local_data_dir(app: &tauri::AppHandle) -> Result pub(crate) struct Managed { pub ctlr_tx: CtlrTx, pub inject_faults: bool, @@ -140,17 +143,29 @@ pub(crate) fn run(params: client::GuiParams) -> Result<()> { let app_handle = app.handle(); let _ctlr_task = tokio::spawn(async move { - if let Err(e) = run_controller( - app_handle, + let result = run_controller( + app_handle.clone(), ctlr_tx, ctlr_rx, logging_handles, advanced_settings, notify_controller, ) - .await - { + .await; + + // See + // This should be the ONLY place we call `app.exit` or `app_handle.exit`, + // because it exits the entire process without dropping anything. + // + // This seems to be a platform limitation that Tauri is unable to hide + // from us. It was the source of much consternation at time of writing. + + if let Err(e) = result { tracing::error!("run_controller returned an error: {e:#?}"); + app_handle.exit(1); + } else { + tracing::debug!("GUI controller task exited cleanly"); + app_handle.exit(0); } }); @@ -219,7 +234,7 @@ fn handle_system_tray_event(app: &tauri::AppHandle, event: TrayMenuEvent) -> Res } TrayMenuEvent::SignIn => ctlr_tx.blocking_send(ControllerRequest::SignIn)?, TrayMenuEvent::SignOut => ctlr_tx.blocking_send(ControllerRequest::SignOut)?, - TrayMenuEvent::Quit => app.exit(0), + TrayMenuEvent::Quit => ctlr_tx.blocking_send(ControllerRequest::Quit)?, } Ok(()) } @@ -230,6 +245,7 @@ pub(crate) enum ControllerRequest { DisconnectedTokenExpired, ExportLogs { path: PathBuf, stem: PathBuf }, GetAdvancedSettings(oneshot::Sender), + Quit, SchemeRequest(url::Url), SignIn, StartStopLogCounting(bool), @@ -515,6 +531,7 @@ async fn run_controller( Req::GetAdvancedSettings(tx) => { tx.send(controller.advanced_settings.clone()).ok(); } + Req::Quit => break, Req::SchemeRequest(url) => if let Err(e) = controller.handle_deep_link(&url).await { tracing::error!("couldn't handle deep link: {e:#?}"); } @@ -557,6 +574,8 @@ async fn run_controller( } } } - tracing::debug!("GUI controller task exiting cleanly"); + + // Last chance to do any drops / cleanup before the process crashes. + Ok(()) }