From 5c1dcd4f970de8e307e2bdd9f546c09fb1a38b97 Mon Sep 17 00:00:00 2001 From: onemannoplan <96282233+onemannoplan@users.noreply.github.com> Date: Thu, 8 Oct 2026 23:53:21 -0500 Subject: [PATCH 1/2] fix(macos): prevent SIGILL crash on exit by replacing viewport close with clean process exit ### Summary When selecting "Quit LightCraft" from the native macOS menu bar, the application occasionally crashes with an `EXC_BAD_INSTRUCTION` (SIGILL) error report during shutdown. ### Root Cause 1. The native menu action triggered `ctx.send_viewport_cmd(egui::ViewportCommand::Close)`. 2. Forcing an explicit viewport close via the command queue while macOS and AppKit are initiating their own termination sequence creates a race condition with `winit`. 3. This conflict during native window, view, and observer teardown leads to an illegal instruction fault. ### Solution - Replaced the manual `ViewportCommand::Close` trigger on `QUIT` with a clean `std::process::exit(0)`. - This bypasses the problematic `winit`/AppKit teardown race condition on macOS, allowing the application to shut down instantly and cleanly without generating crash reports. --- apps/lightcraft/src/native_menu.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/lightcraft/src/native_menu.rs b/apps/lightcraft/src/native_menu.rs index 647f7e27..6c6d2f2b 100644 --- a/apps/lightcraft/src/native_menu.rs +++ b/apps/lightcraft/src/native_menu.rs @@ -360,8 +360,7 @@ impl NativeMenu { lightcraft_ui_egui::i18n::set_language(app.ui.language); while let Ok(key) = self.rx.try_recv() { if key == QUIT { - ctx.send_viewport_cmd(egui::ViewportCommand::Close); - continue; + std::process::exit(0); } if key == "app.about" || key == SETTINGS { let _ = app.run(&key, serde_json::json!({})); From 761631c56cc99ec394f3047fc99bbc059e709283 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Fri, 9 Oct 2026 08:19:34 -0400 Subject: [PATCH 2/2] Quit from the macOS menu: save settings and the library (and honour the unsaved-changes prompt) before exiting std::process::exit skipped eframe's on_exit (ui.json, close_library) and the may_close check, so changes still in memory could be lost on Cmd+Q. Co-Authored-By: Claude Opus 5.5 --- apps/lightcraft/src/main.rs | 11 +++++++++-- apps/lightcraft/src/native_menu.rs | 13 +++++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/apps/lightcraft/src/main.rs b/apps/lightcraft/src/main.rs index a0394da9..aedbf7fb 100644 --- a/apps/lightcraft/src/main.rs +++ b/apps/lightcraft/src/main.rs @@ -52,8 +52,15 @@ struct App(LightcraftApp, PrefsWriter, #[cfg(target_os = "macos")] Option bool { lightcraft_ui_egui::i18n::set_language(app.ui.language); + let mut quit = false; while let Ok(key) = self.rx.try_recv() { if key == QUIT { - std::process::exit(0); + quit = true; + continue; } if key == "app.about" || key == SETTINGS { let _ = app.run(&key, serde_json::json!({})); @@ -374,7 +378,7 @@ impl NativeMenu { let bar = menu_bar(app); if structure_of(&bar) != self.structure { self.rebuild(app); - return; + return quit; } fn walk(nodes: &[MenuNode], items: &mut HashMap) { for n in nodes { @@ -428,6 +432,7 @@ impl NativeMenu { } self.publish_shortcuts(app); } + quit } }