From 433487d16b7b95160158ce9046460fffae88474b Mon Sep 17 00:00:00 2001 From: Tim Johannes Date: Fri, 3 Jul 2026 11:34:28 +0200 Subject: [PATCH 1/2] Fix Linux segfault on application exit (dead GL context in global dtors) On exit, GUI_App::OnExit() called std::exit(0), which drives the C++ global/static destructors. Static GLModel instances are destroyed there and call GLModel::RenderData::release() -> glDeleteBuffers() after the GL/GTK context has already been torn down, dereferencing a stale GL entry point and segfaulting. breakpad's signal handler then double-faults on top. Backtrace (Linux, 7.2.x): GUI_App::OnExit -> std::exit -> -> GLModel::~GLModel -> GLModel::reset -> RenderData::release -> glDeleteBuffers -> SIGSEGV All persistent state is already saved during the window-close sequence and wxApp::OnExit(), so on Linux terminate via std::_Exit(0) to skip the global-destructor teardown. Windows/macOS keep std::exit(0). --- src/slic3r/GUI/GUI_App.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 29506e42..71050595 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -3832,7 +3832,18 @@ int GUI_App::OnExit() int result = wxApp::OnExit(); BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << " end"; boost::log::core::get()->flush(); +#ifdef __linux__ + // On Linux the GL/GTK context is already torn down by the time std::exit() drives + // the global/static destructors. Static GLModel instances then call + // GLModel::RenderData::release() -> glDeleteBuffers() into a dead context, which + // segfaults on shutdown (and breakpad's handler double-faults on top of it). + // All persistent state (AppConfig, presets) has already been saved during the + // window-close sequence and wxApp::OnExit() above, so skip the global-destructor + // teardown entirely and terminate immediately. + std::_Exit(0); +#else std::exit(0); +#endif return 0; } From e0f50fe059b3576f8cd504557f0358d15daec3bf Mon Sep 17 00:00:00 2001 From: Tim Johannes Date: Fri, 3 Jul 2026 11:34:28 +0200 Subject: [PATCH 2/2] Make breakpad dumpCallback exception-safe on Linux dumpCallback() runs from breakpad's signal handler but performs throwing boost::filesystem operations (rename/create_directories). When one throws (e.g. missing crash-dump dir), the exception unwinds out of the signal handler and double-faults into a second, harder crash, losing the minidump. Wrap the body in a catch-all so no exception can escape the handler. --- src/CrealityPrint.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/CrealityPrint.cpp b/src/CrealityPrint.cpp index 4e124b5c..8e86fe32 100644 --- a/src/CrealityPrint.cpp +++ b/src/CrealityPrint.cpp @@ -6709,6 +6709,11 @@ extern "C" { #ifdef USE_BREAKPAD static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,void* context, bool succeeded) { printf("Dump path: %s\n", descriptor.path()); + // This runs from breakpad's signal handler. A C++ exception escaping here + // (e.g. boost::filesystem::rename throwing when the target dir is missing) + // unwinds out of the signal handler and double-faults into a second, harder + // crash. Keep every throwing operation below inside this guard. + try { if (succeeded) { boost::filesystem::path oldPath(descriptor.path()); std::string data_dir = Slic3r::data_dir(); @@ -6763,6 +6768,9 @@ static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,v } else { BOOST_LOG_TRIVIAL(error) << "MiniDump failed: " << descriptor.path(); } + } catch (...) { + // Never let an exception escape the signal handler. + } return succeeded; } #endif