diff --git a/main/gui/source/crash_handlers.cpp b/main/gui/source/crash_handlers.cpp index 096cae2db..8a24b6bdf 100644 --- a/main/gui/source/crash_handlers.cpp +++ b/main/gui/source/crash_handlers.cpp @@ -48,12 +48,13 @@ namespace hex::crash { using CrashCallback = void (*) (const std::string&); static CrashCallback crashCallback = sendNativeMessage; + static std::fs::path s_crashBackupPath; static void saveCrashFile(const std::string& message) { log::fatal("{}", message); const nlohmann::json crashData { { "logFile", wolv::io::fs::toNormalizedPathString(hex::log::impl::getFile().getPath()) }, - { "project", wolv::io::fs::toNormalizedPathString(ProjectFile::getPath()) }, + { "project", wolv::io::fs::toNormalizedPathString(s_crashBackupPath) }, }; for (const auto &path : paths::Config.write()) { @@ -81,11 +82,27 @@ namespace hex::crash { } } - extern "C" [[noreturn]] void triggerSafeShutdown(int signalNumber = 0) { + static void callCrashHandlers(const std::string &msg) { + // Call the crash callback + crashCallback(msg); + + // Print the stacktrace to the console or log file + printStackTrace(); + + // Flush all streams + std::fflush(stdout); + std::fflush(stderr); + + #if defined(IMGUI_TEST_ENGINE) + ImGuiTestEngine_CrashHandler(); + #endif + } + + extern "C" [[noreturn]] void triggerSafeShutdown(std::string crashMessage, int signalNumber = 0) { if (!TaskManager::isMainThread()) { log::error("Terminating from non-main thread, scheduling termination on main thread"); - TaskManager::doLater([signalNumber] { - triggerSafeShutdown(signalNumber); + TaskManager::doLater([=] { + triggerSafeShutdown(crashMessage, signalNumber); }); // Terminate this thread @@ -102,6 +119,7 @@ namespace hex::crash { // Trigger an event so that plugins can handle crashes EventAbnormalTermination::post(signalNumber); + callCrashHandlers(crashMessage); // Run exit tasks init::runExitTasks(); @@ -134,22 +152,6 @@ namespace hex::crash { #endif } - void handleCrash(const std::string &msg) { - // Call the crash callback - crashCallback(msg); - - // Print the stacktrace to the console or log file - printStackTrace(); - - // Flush all streams - std::fflush(stdout); - std::fflush(stderr); - - #if defined(IMGUI_TEST_ENGINE) - ImGuiTestEngine_CrashHandler(); - #endif - } - // Custom signal handler to print various information and a stacktrace when the application crashes static void signalHandler(int signalNumber, const std::string &signalName) { #if !defined (DEBUG) @@ -159,18 +161,12 @@ namespace hex::crash { } #endif - // Reset crash handlers, so we can't have a recursion if this code crashes - resetCrashHandlers(); - - // Actually handle the crash - handleCrash(fmt::format("Received signal '{}' ({})", signalName, signalNumber)); - // Detect if the crash was due to an uncaught exception if (std::uncaught_exceptions() > 0) { log::fatal("Uncaught exception thrown!"); } - triggerSafeShutdown(signalNumber); + triggerSafeShutdown(fmt::format("Received signal '{}' ({})", signalName, signalNumber), signalNumber); } static void uncaughtExceptionHandler() { @@ -184,12 +180,8 @@ namespace hex::crash { else log::fatal("Program terminated due to unknown reason!"); } catch (std::exception &ex) { - std::string exceptionStr = fmt::format("{}()::what() -> {}", trace::demangle(typeid(ex).name()), ex.what()); - - handleCrash(exceptionStr); - log::fatal("Program terminated with uncaught exception: {}", exceptionStr); - - triggerSafeShutdown(); + const auto exceptionStr = fmt::format("Program terminated with uncaught exception: {}()::what() -> {}", trace::demangle(typeid(ex).name()), ex.what()); + triggerSafeShutdown(exceptionStr); } } @@ -255,8 +247,11 @@ namespace hex::crash { // Create crash backup if any providers are open if (ImHexApi::Provider::isValid()) { for (const auto &path : paths::Config.write()) { - if (ProjectFile::store(path / CrashBackupFileName, false)) + if (ProjectFile::store(path / CrashBackupFileName, false)) { + s_crashBackupPath = path / CrashBackupFileName; + log::fatal("Saved crash backup to '{}'", wolv::util::toUTF8String(s_crashBackupPath)); break; + } } } });