diff --git a/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp b/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp index b9ecb782..e2ea3d33 100644 --- a/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp +++ b/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp @@ -1,36 +1,73 @@ #include #include +#include -void handler_SIGSEGV(int sig) +#include "config/CemuConfig.h" + +// handle signals that would dump core, print stacktrace and then dump depending on config +void handlerDumpingSignal(int sig) { - printf("SIGSEGV!\n"); + char* sigName = strsignal(sig); + if (sigName) + { + printf("%s!\n", sigName); + } + else + { + // should never be the case + printf("Unknown core dumping signal!\n"); + } - void *array[32]; - size_t size; + void *array[32]; + size_t size; - // get void*'s for all entries on the stack - size = backtrace(array, 32); + // get void*'s for all entries on the stack + size = backtrace(array, 32); - // print out all the frames to stderr - fprintf(stderr, "Error: signal %d:\n", sig); - backtrace_symbols_fd(array, size, STDERR_FILENO); - exit(1); + // print out all the frames to stderr + fprintf(stderr, "Error: signal %d:\n", sig); + backtrace_symbols_fd(array, size, STDERR_FILENO); + + if (GetConfig().crash_dump == CrashDump::Enabled) + { + // reset signal handler to default and re-raise signal to dump core + signal(sig, SIG_DFL); + raise(sig); + return; + } + // exit process ignoring all issues + _Exit(1); } void handler_SIGINT(int sig) { - /* - * Received when pressing CTRL + C in a console - * Ideally should be exiting cleanly after saving settings but currently - * there's no clean exit pathway (at least on linux) and exiting the app - * by any mean ends up with a SIGABRT from the standard library destroying - * threads. - */ - _Exit(0); + /* + * Received when pressing CTRL + C in a console + * Ideally should be exiting cleanly after saving settings but currently + * there's no clean exit pathway (at least on linux) and exiting the app + * by any mean ends up with a SIGABRT from the standard library destroying + * threads. + */ + _Exit(0); } void ExceptionHandler_init() { - signal(SIGSEGV, handler_SIGSEGV); - signal(SIGINT, handler_SIGINT); + struct sigaction action; + action.sa_flags = 0; + sigfillset(&action.sa_mask); // don't allow signals to be interrupted + + action.sa_handler = handler_SIGINT; + sigaction(SIGINT, &action, nullptr); + + action.sa_handler = handlerDumpingSignal; + sigaction(SIGABRT, &action, nullptr); + sigaction(SIGBUS, &action, nullptr); + sigaction(SIGFPE, &action, nullptr); + sigaction(SIGILL, &action, nullptr); + sigaction(SIGIOT, &action, nullptr); + sigaction(SIGQUIT, &action, nullptr); + sigaction(SIGSEGV, &action, nullptr); + sigaction(SIGSYS, &action, nullptr); + sigaction(SIGTRAP, &action, nullptr); } diff --git a/src/config/CemuConfig.cpp b/src/config/CemuConfig.cpp index f996fc94..dcd283ec 100644 --- a/src/config/CemuConfig.cpp +++ b/src/config/CemuConfig.cpp @@ -316,7 +316,11 @@ void CemuConfig::Load(XMLConfigParser& parser) // debug auto debug = parser.get("Debug"); - crash_dump = debug.get("CrashDump", crash_dump); +#if BOOST_OS_WINDOWS + crash_dump = debug.get("CrashDumpWindows", crash_dump); +#elif BOOST_OS_UNIX + crash_dump = debug.get("CrashDumpUnix", crash_dump); +#endif // input auto input = parser.get("Input"); @@ -487,7 +491,11 @@ void CemuConfig::Save(XMLConfigParser& parser) // debug auto debug = config.set("Debug"); - debug.set("CrashDump", crash_dump.GetValue()); +#if BOOST_OS_WINDOWS + debug.set("CrashDumpWindows", crash_dump.GetValue()); +#elif BOOST_OS_UNIX + debug.set("CrashDumpUnix", crash_dump.GetValue()); +#endif // input auto input = config.set("Input"); diff --git a/src/config/CemuConfig.h b/src/config/CemuConfig.h index 8c43f0a5..caabf082 100644 --- a/src/config/CemuConfig.h +++ b/src/config/CemuConfig.h @@ -172,6 +172,7 @@ enum class CafeConsoleLanguage }; ENABLE_ENUM_ITERATORS(CafeConsoleLanguage, CafeConsoleLanguage::JA, CafeConsoleLanguage::TW); +#if BOOST_OS_WINDOWS enum class CrashDump { Disabled, @@ -179,6 +180,14 @@ enum class CrashDump Full }; ENABLE_ENUM_ITERATORS(CrashDump, CrashDump::Disabled, CrashDump::Full); +#elif BOOST_OS_UNIX +enum class CrashDump +{ + Disabled, + Enabled +}; +ENABLE_ENUM_ITERATORS(CrashDump, CrashDump::Disabled, CrashDump::Enabled); +#endif template <> struct fmt::formatter : formatter { @@ -290,6 +299,7 @@ struct fmt::formatter : formatter { } }; +#if BOOST_OS_WINDOWS template <> struct fmt::formatter : formatter { template @@ -306,6 +316,23 @@ struct fmt::formatter : formatter { return formatter::format(name, ctx); } }; +#elif BOOST_OS_UNIX +template <> +struct fmt::formatter : formatter { + template + auto format(const CrashDump v, FormatContext &ctx) { + string_view name; + switch (v) + { + case CrashDump::Disabled: name = "Disabled"; break; + case CrashDump::Enabled: name = "Enabled"; break; + default: name = "unknown"; break; + + } + return formatter::format(name, ctx); + } +}; +#endif struct CemuConfig diff --git a/src/gui/GeneralSettings2.cpp b/src/gui/GeneralSettings2.cpp index f81e7364..6c4f5bbb 100644 --- a/src/gui/GeneralSettings2.cpp +++ b/src/gui/GeneralSettings2.cpp @@ -709,10 +709,18 @@ wxPanel* GeneralSettings2::AddDebugPage(wxNotebook* notebook) debug_row->Add(new wxStaticText(panel, wxID_ANY, _("Crash dump"), wxDefaultPosition, wxDefaultSize, 0), 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); +#if BOOST_OS_WINDOWS wxString dump_choices[] = { _("Disabled"), _("Lite"), _("Full") }; +#elif BOOST_OS_UNIX + wxString dump_choices[] = { _("Disabled"), _("Enabled") }; +#endif m_crash_dump = new wxChoice(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, std::size(dump_choices), dump_choices); m_crash_dump->SetSelection(0); +#if BOOST_OS_WINDOWS m_crash_dump->SetToolTip(_("Creates a dump when Cemu crashes\nOnly enable when requested by a developer!\nThe Full option will create a very large dump file (includes a full RAM dump of the Cemu process)")); +#elif BOOST_OS_UNIX + m_crash_dump->SetToolTip(_("Creates a core dump when Cemu crashes\nOnly enable when requested by a developer!")); +#endif debug_row->Add(m_crash_dump, 0, wxALL | wxEXPAND, 5); debug_panel_sizer->Add(debug_row, 0, wxALL | wxEXPAND, 5);