fix(macos): prevent Bambu network plugin SIGABRT on app quit

libbambu_networking aborts inside its C++ static destructors during the
exit() teardown on macOS while its background threads are still alive.
Two quit paths reach that exit():

- App menu / Dock / logout: -[NSApplication terminate:] -> exit() bypasses
  wx OnExit()/~GUI_App. Override OSXOnWillTerminate() (the last wx hook
  before that exit()) to hard-exit via std::_Exit(0).
- Cmd+Q / File>Quit / red button: graceful close -> ~GUI_App(). A guarded
  std::_Exit(0) at the end of ~GUI_App(), after all cleanup, covers it.

macOS-only (#ifdef __APPLE__); Windows/Linux unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Walter Almada B
2026-07-02 16:37:24 -07:00
parent b3102b3f70
commit f1948f429c
2 changed files with 38 additions and 0 deletions

View File

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

View File

@ -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();