From ae2362752c28ae111db2ff4df3ca70ae38604400 Mon Sep 17 00:00:00 2001 From: ebbicott Date: Thu, 8 Oct 2026 15:13:39 -0400 Subject: [PATCH] =?UTF-8?q?Shut=20plugin=20hosting=20down=20in=20on=5Fexit?= =?UTF-8?q?:=20=E2=8C=98Q=20exits=20from=20inside=20the=20event=20loop?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The system Quit (⌘Q, or a quit Apple Event) goes through -[NSApplication terminate:], which calls exit() from inside the event loop, so eframe::run_native never returns and the shutdown placed after it never ran. With HALion Sonic in use, the exit handler then ran its bundleExit too late and the app crashed on quit ("quit unexpectedly", found in manual testing). eframe calls on_exit on every way out, so the app now releases its player (and with it the plugin instances) and shuts plugin hosting down there. Refs #16 Co-Authored-By: Claude Opus 5.5 --- apps/soundcraft/src/main.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/soundcraft/src/main.rs b/apps/soundcraft/src/main.rs index c38ea6b..295b1dd 100644 --- a/apps/soundcraft/src/main.rs +++ b/apps/soundcraft/src/main.rs @@ -39,6 +39,10 @@ impl eframe::App for App { } fn on_exit(&mut self) { save_prefs(&self.0.ui); + // The system Quit (⌘Q) ends the process from inside the event loop, so `run_native` never + // returns: release the player's plugin instances and shut plugin hosting down here. + self.0.player = None; + soundcraft_engine::shutdown_plugin_hosts(); } } @@ -168,7 +172,7 @@ fn main() -> eframe::Result { if let Some(icon) = app_icon() { options.viewport = options.viewport.with_icon(icon); } - let result = eframe::run_native( + eframe::run_native( "SoundCraft", options, Box::new(move |cc| { @@ -188,8 +192,5 @@ fn main() -> eframe::Result { } Ok(Box::new(App(app))) }), - ); - // The app, its player and their plugin instances are gone once the event loop returns. - soundcraft_engine::shutdown_plugin_hosts(); - result + ) }