diff --git a/externals/sdl3 b/externals/sdl3 index d5af35e3f..7f12b975b 160000 --- a/externals/sdl3 +++ b/externals/sdl3 @@ -1 +1 @@ -Subproject commit d5af35e3fbb5bb6555ed00e69740d52af2a4e877 +Subproject commit 7f12b975bbad1b35f63c1b7090bf3e99575d95df diff --git a/src/common/logging/log.cpp b/src/common/logging/log.cpp index df0b09f3e..baa618fc0 100644 --- a/src/common/logging/log.cpp +++ b/src/common/logging/log.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "common/assert.h" #include "common/config.h" @@ -15,6 +16,14 @@ #include #endif +// return codes above 'standard' +// https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes +enum class ShadPs4ReturnCode : u32 { + TERMINATE_WITHOUT_EXCEPTION = 20'000, + TERMINATE_WITH_EXCEPTION = 20'001, + TERMINATE_WITH_UNKNOWN_EXCEPTION = 20'002, +}; + namespace Common::Log { bool g_should_append = false; @@ -169,6 +178,7 @@ void Setup(std::string_view log_filename) { already_registered = true; std::atexit(Shutdown); std::at_quick_exit(Flush); + std::set_terminate(Terminate); } #ifdef _WIN32 @@ -258,4 +268,24 @@ void Flush() { g_console_sink->flush(); } } + +void Terminate() { + try { + if (std::exception_ptr eptr{std::current_exception()}) { + std::rethrow_exception(eptr); + } + + LOG_CRITICAL(Debug, "Exiting without exception"); + + std::quick_exit(std::to_underlying(ShadPs4ReturnCode::TERMINATE_WITHOUT_EXCEPTION)); + } catch (const std::exception& exception) { + LOG_CRITICAL(Debug, "Exception: {}", exception); + + std::quick_exit(std::to_underlying(ShadPs4ReturnCode::TERMINATE_WITH_EXCEPTION)); + } catch (...) { + LOG_CRITICAL(Debug, "Unknown exception caught"); + + std::quick_exit(std::to_underlying(ShadPs4ReturnCode::TERMINATE_WITH_UNKNOWN_EXCEPTION)); + } +} } // namespace Common::Log diff --git a/src/common/logging/log.h b/src/common/logging/log.h index e5aaae0ab..2be10e873 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h @@ -35,6 +35,8 @@ void Shutdown(); void Flush(); +void Terminate(); + static constexpr std::array level_string_views{"Trace", "Debug", "Info", "Warning", "Error", "Critical", "Off"}; diff --git a/src/core/libraries/kernel/threads/pthread.cpp b/src/core/libraries/kernel/threads/pthread.cpp index b86536aec..05ded58ac 100644 --- a/src/core/libraries/kernel/threads/pthread.cpp +++ b/src/core/libraries/kernel/threads/pthread.cpp @@ -210,6 +210,10 @@ static void* RunThread(void* arg) { curthread->native_thr.Initialize(); +#ifdef WIN32 + std::set_terminate(Common::Log::Terminate); +#endif + /* Run the current thread's start routine with argument: */ auto* const stack = (void*)(((size_t)curthread->attr.stackaddr_attr + curthread->attr.stacksize_attr) & (~15)); diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 0d591c9e9..912a1cfa0 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -111,6 +111,8 @@ void Linker::Execute(const std::vector& args) { main_thread.Run([this, module, &args](std::stop_token) { Common::SetCurrentThreadName("Game:Main"); + std::set_terminate(Common::Log::Terminate); + #ifndef _WIN32 // Clear any existing signal mask for game threads. sigset_t emptyset; sigemptyset(&emptyset); diff --git a/src/core/signals.cpp b/src/core/signals.cpp index f9b45bab7..8ed0ecf41 100644 --- a/src/core/signals.cpp +++ b/src/core/signals.cpp @@ -31,9 +31,16 @@ namespace Core { static LONG WINAPI SignalHandler(EXCEPTION_POINTERS* pExp) noexcept { const auto* signals = Signals::Instance(); + DWORD code = 0; + PVOID address = nullptr; + + if (pExp != nullptr && pExp->ExceptionRecord != nullptr) { + code = pExp->ExceptionRecord->ExceptionCode; + address = pExp->ExceptionRecord->ExceptionAddress; + } bool handled = false; - switch (pExp->ExceptionRecord->ExceptionCode) { + switch (code) { case EXCEPTION_ACCESS_VIOLATION: handled = signals->DispatchAccessViolation( pExp, reinterpret_cast(pExp->ExceptionRecord->ExceptionInformation[1])); @@ -49,7 +56,14 @@ static LONG WINAPI SignalHandler(EXCEPTION_POINTERS* pExp) noexcept { break; } - return handled ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH; + if (handled) { + return EXCEPTION_CONTINUE_EXECUTION; + } + + LOG_CRITICAL(Debug, "Unhandled Exception code {:#x} at {}", code, address); + Common::Log::Flush(); + + return EXCEPTION_CONTINUE_SEARCH; } #else