diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 37e9043664..327e7b8be8 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -2215,6 +2215,16 @@ GUI_App::~GUI_App() BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< boost::format(": exit"); + +#ifdef __APPLE__ + // Belt-and-suspenders for the graceful quit path (Cmd+Q / File>Quit / red button), + // which reaches ~GUI_App() instead of OSXOnWillTerminate(). All app cleanup has run + // by this point (config saved, network agent deleted, Bambu plugin shut down), so we + // hard-exit to ensure the C runtime's exit() never runs libbambu_networking's static + // destructors — they abort during teardown on macOS. This mirrors the app-menu/Dock/ + // logout path handled in GUI_App::OSXOnWillTerminate(). + std::_Exit(0); +#endif /* __APPLE__ */ } bool GUI_App::is_blocking_printing(MachineObject *obj_) @@ -2593,6 +2603,30 @@ int GUI_App::OnExit() return wxApp::OnExit(); } +#ifdef __APPLE__ +// On macOS, quitting via the app menu / Dock / logout (or a system Quit AppleEvent) +// routes through Cocoa's -[NSApplication terminate:], which calls exit() directly +// from inside the native run loop. That bypasses wx's normal shutdown +// (OnExit()/~GUI_App never run) and, during __cxa_finalize_ranges, runs the C++ +// static/atexit destructors of the closed-source Bambu networking plugin +// (libbambu_networking) while its background threads are still alive. One of those +// destructors calls std::terminate() -> abort(), producing a SIGABRT crash report +// *after* the user has already quit (purely a teardown crash, no data at risk). +// +// OSXOnWillTerminate() is the last wx hook invoked before that exit(), and only +// runs once termination has already been approved (OSXOnShouldTerminate() returned +// no veto). We let the base class fire wxEVT_END_SESSION for any listeners, then +// hard-exit with _Exit() so __cxa_finalize_ranges — and thus the plugin's crashing +// destructors — never run. Nothing is persisted on this path today either, so this +// is behavior-preserving apart from removing the cosmetic crash. +void GUI_App::OSXOnWillTerminate() +{ + BOOST_LOG_TRIVIAL(info) << "GUI_App::OSXOnWillTerminate: hard-exit to avoid Bambu network plugin teardown crash"; + wxApp::OSXOnWillTerminate(); + std::_Exit(0); +} +#endif /* __APPLE__ */ + class wxBoostLog : public wxLog { void DoLogText(const wxString &msg) override { diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index c749280ed3..472aadeb41 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -626,6 +626,10 @@ public: // wxWidgets override to get an event on open files. void MacOpenFiles(const wxArrayString &fileNames) override; void MacOpenURL(const wxString& url) override; + // Last wx hook before Cocoa's exit() on the app-menu/Dock/logout quit path. + // Hard-exits to skip the crashing static-destructor teardown of the Bambu + // networking plugin. See implementation in GUI_App.cpp. + void OSXOnWillTerminate() override; #endif /* __APPLE */ Sidebar& sidebar();