From 94ef03dcd2ff049e4da2dbfb206de43d504a20fd Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sun, 21 Sep 2025 14:08:15 -0500 Subject: [PATCH] Add cpptrace in I_Error on windows, minidumps, stricter warnings, optimized drawers in debug --- CMakeLists.txt | 3 + CMakePresets.json | 8 +- src/CMakeLists.txt | 67 ++++++++++- src/doomdef.h | 2 +- src/i_system.h | 2 +- src/menus/options-voice.cpp | 2 +- src/objects/monitor.c | 1 + src/r_segs.cpp | 6 +- src/sdl/i_main.cpp | 70 +---------- src/sdl/i_system.cpp | 228 +++++++++++++++++++++++++++++++++--- vcpkg.json | 4 + 11 files changed, 294 insertions(+), 99 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f9c457546..fc82385dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,6 +125,9 @@ find_package(PNG REQUIRED) find_package(SDL2 CONFIG REQUIRED) find_package(CURL REQUIRED) find_package(Opus REQUIRED) +if(WIN32 AND NOT MINGW) + find_package(cpptrace CONFIG REQUIRED) +endif() # Use the one in thirdparty/fmt to guarantee a minimum version #find_package(FMT CONFIG REQUIRED) diff --git a/CMakePresets.json b/CMakePresets.json index 199d9bcf4..a52a087bd 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -54,8 +54,8 @@ "name": "__develop-cl", "hidden": true, "cacheVariables": { - "CMAKE_C_FLAGS_RELWITHDEBINFO": "/MD /O2 /Ob2 /DNDEBUG", - "CMAKE_CXX_FLAGS_RELWITHDEBINFO": "/MD /O2 /Ob2 /DNDEBUG", + "CMAKE_C_FLAGS_RELWITHDEBINFO": "/MD /Zi /O2 /Ob2 /DNDEBUG", + "CMAKE_CXX_FLAGS_RELWITHDEBINFO": "/MD /Zi /O2 /Ob2 /DNDEBUG", "SRB2_CONFIG_DEV_BUILD": "ON", "CMAKE_BUILD_TYPE": "RelWithDebInfo" } @@ -64,8 +64,8 @@ "name": "__release-cl", "hidden": true, "cacheVariables": { - "CMAKE_C_FLAGS_RELWITHDEBINFO": "/MD /O2 /Ob2 /DNDEBUG", - "CMAKE_CXX_FLAGS_RELWITHDEBINFO": "/MD /O2 /Ob2 /DNDEBUG", + "CMAKE_C_FLAGS_RELWITHDEBINFO": "/MD /Zi /O2 /Ob2 /DNDEBUG", + "CMAKE_CXX_FLAGS_RELWITHDEBINFO": "/MD /Zi /O2 /Ob2 /DNDEBUG", "SRB2_CONFIG_DEV_BUILD": "OFF", "CMAKE_BUILD_TYPE": "RelWithDebInfo" } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e3bb3c070..35e8cb1ca 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -176,6 +176,41 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 p_deepcopy.cpp ) +# Always compile some files with optimizations in Debug config. +# This is to make the debugging experience less slow for the majority of cases. +set(always_optimize_options "") +if(MSVC) + set(always_optimize_options "$<$:/O2;/Ob2>") +else() + set(always_optimize_options "$<$:-O3>") +endif() +set_source_files_properties( + r_bsp.cpp + r_data.c + r_debug.cpp + r_debug_parser.cpp + r_debug_printer.cpp + r_draw.cpp + r_fps.cpp + r_main.cpp + r_plane.cpp + r_segs.cpp + r_skins.c + r_sky.c + r_splats.c + r_spritefx.cpp + r_things.cpp + r_bbox.c + r_textures.cpp + r_textures_dups.cpp + r_patch.cpp + r_patchrotation.c + r_picformats.c + r_portal.c + PROPERTIES + COMPILE_OPTIONS "${always_optimize_options}" +) + set_target_properties(SRB2SDL2 PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/sdl/macosx/MacOSXBundleInfo.plist.in") if(SRB2_CONFIG_ENABLE_WEBM_MOVIES) @@ -210,7 +245,7 @@ add_custom_target(_SRB2_reconf ALL ) add_dependencies(SRB2SDL2 _SRB2_reconf) -if(("${CMAKE_COMPILER_IS_GNUCC}" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND "${CMAKE_SYSTEM_NAME}" MATCHES "Windows") +if(("${CMAKE_COMPILER_IS_GNUCC}") AND "${CMAKE_SYSTEM_NAME}" MATCHES "Windows") target_link_options(SRB2SDL2 PRIVATE "-Wl,--disable-dynamicbase") if("${SRB2_CONFIG_STATIC_STDLIB}") # On MinGW with internal libraries, link the standard library statically @@ -224,8 +259,19 @@ if(("${CMAKE_COMPILER_IS_GNUCC}" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND endif() endif() -if(MSVC OR CMAKE_CXX_LINK_EXECUTABLE MATCHES "lld-link.exe") +if(MSVC OR CMAKE_CXX_LINK_EXECUTABLE MATCHES "lld-link\\.exe") target_link_options(SRB2SDL2 PRIVATE /MANIFEST:NO) + target_link_libraries(SRB2SDL2 PRIVATE "dbghelp") + +endif() + +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND MSVC) + # Stuff to make paths not include the builder's file system paths on clang-cl + string(REPLACE "/" "\\" backslashes_cmake_source_dir "${CMAKE_SOURCE_DIR}") + target_compile_options(SRB2SDL2 PRIVATE "$<$:/clang:-fdebug-prefix-map=${CMAKE_SOURCE_DIR}=X:/ringracers>") + target_compile_options(SRB2SDL2 PRIVATE "$<$:/clang:-fdebug-prefix-map=${backslashes_cmake_source_dir}=X:/ringracers>") + target_compile_options(SRB2SDL2 PRIVATE "$<$:/clang:-fdebug-compilation-dir=${CMAKE_SOURCE_DIR}>") + target_link_options(SRB2SDL2 PRIVATE "$<$:/pdbaltpath:%_PDB%>") endif() target_compile_features(SRB2SDL2 PRIVATE c_std_11 cxx_std_17) @@ -283,6 +329,10 @@ target_link_libraries(SRB2SDL2 PRIVATE ZLIB::ZLIB) target_link_libraries(SRB2SDL2 PRIVATE PNG::PNG) target_link_libraries(SRB2SDL2 PRIVATE CURL::libcurl) target_link_libraries(SRB2SDL2 PRIVATE Opus::opus) +if(WIN32 AND NOT MINGW) + target_link_libraries(SRB2SDL2 PRIVATE cpptrace::cpptrace) + target_compile_definitions(SRB2SDL2 PRIVATE HAVE_CPPTRACE) +endif() target_link_libraries(SRB2SDL2 PRIVATE ReNameNoise::renamenoise) if("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD") target_link_libraries(SRB2SDL2 PRIVATE -lexecinfo) @@ -461,6 +511,7 @@ target_compile_options(SRB2SDL2 PRIVATE # This is a direct translation from versions.mk $<$,$>: -Wall + -Werror-implicit-function-declaration -Wno-trigraphs -W # Was controlled by RELAXWARNINGS -pedantic @@ -545,6 +596,7 @@ target_compile_options(SRB2SDL2 PRIVATE $<$,$,$>>: #-Wall -Werror=microsoft + -Werror=implicit-function-declaration -Wreturn-type # Missing returns in non-void function -Wduplicate-decl-specifier -Wsometimes-uninitialized @@ -570,9 +622,14 @@ target_compile_options(SRB2SDL2 PRIVATE # C++, GNU $<$,$>: -Wall + -Wno-c++98-compat + -Wno-c++11-compat + -Wno-c++14-compat # No C++14 compat needed + -Werror=c++20-extensions + -Werror=c++23-extensions # Disallow newer language features entirely > - # C++, GNU, Clang and Apple Clang + # C++, Clang and Apple Clang $<$,$,$>>: #-Wall -Werror=microsoft @@ -584,6 +641,8 @@ target_compile_options(SRB2SDL2 PRIVATE -Wno-c++98-compat -Wno-c++11-compat -Wno-c++14-compat # No C++14 compat needed + -Werror=c++20-extensions + -Werror=c++23-extensions # Disallow newer language features entirely -Wno-unused-but-set-variable # Setting unread variables is fine (nontrivial C++ types issue) -Wno-misleading-indentation # Some cases in code currently -Wno-deprecated-non-prototype # We have no intention of using C23 yet. @@ -594,6 +653,8 @@ target_compile_options(SRB2SDL2 PRIVATE -Wno-unused-function > + # C++, Clang and Apple Clang + # C++, MSVC $<$,$>: /Wv:19.20.27004.0 diff --git a/src/doomdef.h b/src/doomdef.h index 78452959c..a2a35144e 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -457,7 +457,7 @@ enum { */ -void I_Error(const char *error, ...) FUNCIERROR; +FUNCIERROR void ATTRNORETURN I_Error(const char *error, ...); /** \brief write a message to stderr (use before I_Quit) for when you need to quit with a msg, but need the return code 0 of I_Quit(); diff --git a/src/i_system.h b/src/i_system.h index ec58097fb..56d507e90 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -92,7 +92,7 @@ void I_OsPolling(void); /** \brief Called by M_Responder when quit is selected, return exit code 0 */ -void I_Quit(void) FUNCNORETURN; +FUNCNORETURN void ATTRNORETURN I_Quit(void); typedef enum { diff --git a/src/menus/options-voice.cpp b/src/menus/options-voice.cpp index d69cd6520..c811db4b9 100644 --- a/src/menus/options-voice.cpp +++ b/src/menus/options-voice.cpp @@ -29,7 +29,7 @@ menuitem_t OPTIONS_Voice[] = NULL, srb2::itemaction(&cv_voice_inputamp), 0, 0}, {IT_STRING | IT_CVAR, "Input Noise Suppression", "Suppress background noise from your voice.", - NULL, {.cvar = &cv_voice_denoise}, 0, 0}, + NULL, srb2::itemaction(&cv_voice_denoise), 0, 0}, {IT_STRING | IT_CVAR, "Input Sensitivity", "Voice higher than this threshold will transmit, in decibels.", NULL, srb2::itemaction(&cv_voice_activationthreshold), 0, 0 }, diff --git a/src/objects/monitor.c b/src/objects/monitor.c index 2bce56847..1545bee78 100644 --- a/src/objects/monitor.c +++ b/src/objects/monitor.c @@ -11,6 +11,7 @@ #include "../doomdef.h" #include "../doomstat.h" #include "../info.h" +#include "../g_game.h" #include "../k_objects.h" #include "../p_local.h" #include "../r_state.h" diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 0867960f5..f863b43b4 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -732,8 +732,7 @@ void R_RenderMaskedSegRange(drawseg_t *drawseg, INT32 x1, INT32 x2) template static constexpr T saturating_add(T x, T y) noexcept { - INT64 z; - z = static_cast(x) + static_cast(y); + INT64 z = static_cast(x) + static_cast(y); if (z > static_cast(std::numeric_limits::max())) { z = static_cast(std::numeric_limits::max()); @@ -748,8 +747,7 @@ static constexpr T saturating_add(T x, T y) noexcept template static constexpr T saturating_mul(T x, T y) noexcept { - INT64 z; - z = static_cast(x) * static_cast(y); + INT64 z = static_cast(x) * static_cast(y); if (z > static_cast(std::numeric_limits::max())) { z = static_cast(std::numeric_limits::max()); diff --git a/src/sdl/i_main.cpp b/src/sdl/i_main.cpp index e4bbbb894..f2fa2fce9 100644 --- a/src/sdl/i_main.cpp +++ b/src/sdl/i_main.cpp @@ -20,7 +20,6 @@ #include "../core/string.h" #include -#include #include @@ -32,11 +31,7 @@ #include #endif -extern "C" { #include "time.h" // For log timestamps -} - -#ifdef HAVE_SDL #ifdef HAVE_TTF #include "SDL.h" @@ -68,46 +63,6 @@ char logfilename[1024]; #endif #endif -#if defined (_WIN32) -extern "C" { -#include "../win32/win_dbg.h" -} -typedef BOOL (WINAPI *p_IsDebuggerPresent)(VOID); -#endif - -#if defined (_WIN32) -static inline VOID MakeCodeWritable(VOID) -{ -#ifdef USEASM // Disable write-protection of code segment - DWORD OldRights; - const DWORD NewRights = PAGE_EXECUTE_READWRITE; - PBYTE pBaseOfImage = (PBYTE)GetModuleHandle(NULL); - PIMAGE_DOS_HEADER dosH =(PIMAGE_DOS_HEADER)pBaseOfImage; - PIMAGE_NT_HEADERS ntH = (PIMAGE_NT_HEADERS)(pBaseOfImage + dosH->e_lfanew); - PIMAGE_OPTIONAL_HEADER oH = (PIMAGE_OPTIONAL_HEADER) - ((PBYTE)ntH + sizeof (IMAGE_NT_SIGNATURE) + sizeof (IMAGE_FILE_HEADER)); - LPVOID pA = pBaseOfImage+oH->BaseOfCode; - SIZE_T pS = oH->SizeOfCode; -#if 1 // try to find the text section - PIMAGE_SECTION_HEADER ntS = IMAGE_FIRST_SECTION (ntH); - WORD s; - for (s = 0; s < ntH->FileHeader.NumberOfSections; s++) - { - if (memcmp (ntS[s].Name, ".text\0\0", 8) == 0) - { - pA = pBaseOfImage+ntS[s].VirtualAddress; - pS = ntS[s].Misc.VirtualSize; - break; - } - } -#endif - - if (!VirtualProtect(pA,pS,NewRights,&OldRights)) - I_Error("Could not make code writable\n"); -#endif -} -#endif - #ifdef LOGMESSAGES static void InitLogging(void) { @@ -212,10 +167,6 @@ static void init_exchndl() if (pfnExcHndlInit != NULL) (pfnExcHndlInit)(); } -#else -static void init_exchndl() -{ -} #endif #ifdef _WIN32 @@ -300,25 +251,12 @@ int main(int argc, char **argv) //I_OutputMsg("I_StartupSystem() ...\n"); I_StartupSystem(); -#if defined (_WIN32) + +#if defined (_WIN32) && !defined(_MSC_VER) if (!M_CheckParm("-noexchndl")) { -#if 0 // just load the DLL - p_IsDebuggerPresent pfnIsDebuggerPresent = (p_IsDebuggerPresent)GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsDebuggerPresent"); - if ((!pfnIsDebuggerPresent || !pfnIsDebuggerPresent()) -#ifdef BUGTRAP - && !InitBugTrap() -#endif - ) -#endif - { - init_exchndl(); - } + init_exchndl(); } -#ifndef __MINGW32__ - prevExceptionFilter = SetUnhandledExceptionFilter(RecordExceptionInfo); -#endif - MakeCodeWritable(); #endif try { @@ -353,8 +291,6 @@ int main(int argc, char **argv) return 0; } -#endif - #ifdef _MSC_VER int WINAPI WinMain(HINSTANCE pInstance, HINSTANCE pPrevInstance, LPSTR lpCmdLine, int nShowCmd) { diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index 31115219c..827f493b1 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -39,6 +39,12 @@ typedef DWORD (WINAPI *p_timeGetTime) (void); typedef UINT (WINAPI *p_timeEndPeriod) (UINT); typedef HANDLE (WINAPI *p_OpenFileMappingA) (DWORD, BOOL, LPCSTR); typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); + +#if defined(_WIN32) && !defined(__GNUC__) +#define USE_DBGHELP +#include +#endif + #endif #include #include @@ -141,6 +147,10 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #define UNIXBACKTRACE #endif +#ifdef HAVE_CPPTRACE +#include +#endif + // Locations for searching for bios.pk3 #if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) #define DEFAULTWADLOCATION1 "/usr/local/share/games/RingRacers" @@ -302,8 +312,10 @@ static void I_ShowErrorMessageBox(const char *messagefordevelopers, boolean dump dumpmade ? #if defined (UNIXBACKTRACE) "crash-log.txt" -#elif defined (_WIN32) +#elif defined (_WIN32) && defined(__GNUC__) ".rpt crash dump" +#elif defined (USE_DBGHELP) + ".dmp crash dump" #endif " (very important!) and " : "", #ifdef LOGMESSAGES @@ -369,12 +381,83 @@ static void I_ShowErrorMessageBox(const char *messagefordevelopers, boolean dump // in case the fullscreen window blocks it for some absurd reason. } -static void I_ReportSignal(int num, int coredumped) +static void I_ReportSignal(int num, int coredumped, void* tracefromcpptrace) { //static char msg[] = "oh no! back to reality!\r\n"; const char * sigmsg; - char msg[128]; + char msg[8192]; +#ifdef USE_DBGHELP + // The signal code is a WIN32 exception code, not a libc signal + // https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-exception_record + switch (num) + { + case EXCEPTION_ACCESS_VIOLATION: + sigmsg = "EXCEPTION_ACCESS_VIOLATION"; + break; + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: + sigmsg = "EXCEPTION_ARRAY_BOUNDS_EXCEEDED"; + break; + case EXCEPTION_BREAKPOINT: + sigmsg = "EXCEPTION_BREAKPOINT"; + break; + case EXCEPTION_DATATYPE_MISALIGNMENT: + sigmsg = "EXCEPTION_DATATYPE_MISALIGNMENT"; + break; + case EXCEPTION_FLT_DENORMAL_OPERAND: + sigmsg = "EXCEPTION_FLT_DENORMAL_OPERAND"; + break; + case EXCEPTION_FLT_DIVIDE_BY_ZERO: + sigmsg = "EXCEPTION_FLT_DENORMAL_OPERAND"; + break; + case EXCEPTION_FLT_INEXACT_RESULT: + sigmsg = "EXCEPTION_FLT_INEXACT_RESULT"; + break; + case EXCEPTION_FLT_INVALID_OPERATION: + sigmsg = "EXCEPTION_FLT_INVALID_OPERATION"; + break; + case EXCEPTION_FLT_OVERFLOW: + sigmsg = "EXCEPTION_FLT_OVERFLOW"; + break; + case EXCEPTION_FLT_STACK_CHECK: + sigmsg = "EXCEPTION_FLT_STACK_CHECK"; + break; + case EXCEPTION_FLT_UNDERFLOW: + sigmsg = "EXCEPTION_FLT_UNDERFLOW"; + break; + case EXCEPTION_ILLEGAL_INSTRUCTION: + sigmsg = "EXCEPTION_ILLEGAL_INSTRUCTION"; + break; + case EXCEPTION_IN_PAGE_ERROR: + sigmsg = "EXCEPTION_IN_PAGE_ERROR"; + break; + case EXCEPTION_INT_DIVIDE_BY_ZERO: + sigmsg = "EXCEPTION_INT_DIVIDE_BY_ZERO"; + break; + case EXCEPTION_INT_OVERFLOW: + sigmsg = "EXCEPTION_INT_OVERFLOW"; + break; + case EXCEPTION_INVALID_DISPOSITION: + sigmsg = "EXCEPTION_INVALID_DISPOSITION"; + break; + case EXCEPTION_NONCONTINUABLE_EXCEPTION: + sigmsg = "EXCEPTION_NONCONTINUABLE_EXCEPTION"; + break; + case EXCEPTION_PRIV_INSTRUCTION: + sigmsg = "EXCEPTION_PRIV_INSTRUCTION"; + break; + case EXCEPTION_SINGLE_STEP: + sigmsg = "EXCEPTION_SINGLE_STEP"; + break; + case EXCEPTION_STACK_OVERFLOW: + sigmsg = "EXCEPTION_STACK_OVERFLOW"; + break; + default: + sigmsg = ""; + sprintf(msg, "unknown exception %d", num); + break; + } +#else switch (num) { // case SIGINT: @@ -405,30 +488,132 @@ static void I_ReportSignal(int num, int coredumped) else sigmsg = msg; } +#endif + if (sigmsg) + { + strcpy(msg, sigmsg); + } if (coredumped) { - if (sigmsg) - strcpy(msg, sigmsg); strcat(msg, " (core dumped)"); - - sigmsg = msg; } +#ifdef HAVE_CPPTRACE + strncat(msg, "\n", sizeof(msg) - strlen(msg) - 1); + + cpptrace::stacktrace const& trace = *(cpptrace::stacktrace*)tracefromcpptrace; + bool firstfound = false; +#ifndef _WIN32 + firstfound = true; +#endif + for (const auto& frame : trace) + { +#ifdef _WIN32 + // dumb hack, unsure if it works on anything other than windows 10-11 + if (!firstfound && frame.symbol == "KiUserExceptionDispatcher") + { + firstfound = true; + continue; + } + if (!firstfound) + { + continue; + } +#endif + + srb2::String frame_str; + if (!frame.filename.empty() && frame.line.has_value()) + { + frame_str = srb2::format("{} at {}:{}\n", frame.symbol, frame.filename, frame.line.value_or(0)); + } + else if (!frame.filename.empty() && !frame.line.has_value()) + { + frame_str = srb2::format("{} at {}\n", frame.symbol, frame.filename); + } + else + { + frame_str = srb2::format("{}\n", frame.symbol); + } + + strncat(msg, frame_str.c_str(), sizeof(msg) - strlen(msg) - 1); + } +#endif + + sigmsg = msg; + I_OutputMsg("\nProcess killed by signal: %s\n\n", sigmsg); I_ShowErrorMessageBox(sigmsg, #if defined (UNIXBACKTRACE) true -#elif defined (_WIN32) +#elif defined (_WIN32) && defined (__GNUC__) !M_CheckParm("-noexchndl") +#elif defined (USE_DBGHELP) + true #else false #endif ); } -#ifndef NEWSIGNALHANDLER +#if !defined(NEWSIGNALHANDLER) || defined(USE_DBGHELP) +static void CommonSignalHandleCleanup(void) +{ + D_QuitNetGame(); // Fix server freezes + CL_AbortDownloadResume(); + G_DirtyGameData(); +} +#endif + +#ifdef USE_DBGHELP +LPTOP_LEVEL_EXCEPTION_FILTER g_previous_toplevelexceptionfilter; + +static LONG WriteMinidumpExceptionFilter(PEXCEPTION_POINTERS ExceptionInfo) +{ +#ifdef HAVE_CPPTRACE + // Fully aware this is completely signal unsafe. We don't ever try to recover from signals, so who cares. + // If it breaks it breaks. We're not mission critical software. + cpptrace::stacktrace trace = cpptrace::generate_trace(0, 30); +#else + int trace = 0; +#endif + + MINIDUMP_EXCEPTION_INFORMATION mei {}; + mei.ExceptionPointers = ExceptionInfo; + mei.ClientPointers = TRUE; + mei.ThreadId = GetCurrentThreadId(); + HANDLE outfile; + + char outfilename[1024]; + GetModuleFileNameA(NULL, outfilename, sizeof(outfilename)); + strncat(outfilename, ".dmp", sizeof(outfilename) - strlen(outfilename) - 1); + + outfile = CreateFileA(outfilename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); + if (outfile == NULL) + { + return EXCEPTION_CONTINUE_SEARCH; + } + + BOOL result; + result = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), outfile, MiniDumpNormal, &mei, NULL, NULL); + if (result == FALSE) + { + CloseHandle(outfile); + DeleteFileA("ringracers_minidump.dmp"); + goto exit; + } + + CloseHandle(outfile); + +exit: + CommonSignalHandleCleanup(); + I_ReportSignal(ExceptionInfo->ExceptionRecord->ExceptionCode, 0, (void*)&trace); + return EXCEPTION_CONTINUE_SEARCH; +} +#endif + +#if !defined(NEWSIGNALHANDLER) && !defined(USE_DBGHELP) static ATTRNORETURN void signal_handler(INT32 num) { g_in_exiting_signal_handler = true; @@ -441,18 +626,20 @@ static ATTRNORETURN void signal_handler(INT32 num) exit(-2); } - D_QuitNetGame(); // Fix server freezes - CL_AbortDownloadResume(); - G_DirtyGameData(); + CommonSignalHandleCleanup(); #ifdef UNIXBACKTRACE write_backtrace(num); #endif - I_ReportSignal(num, 0); + I_ReportSignal(num, 0, NULL); signal(num, SIG_DFL); //default signal action raise(num); } #endif +#ifdef USE_DBGHELP +LPTOP_LEVEL_EXCEPTION_FILTER g_prevtoplevelexceptionfilter; +#endif + FUNCNORETURN static ATTRNORETURN void quit_handler(int num) { signal(num, SIG_DFL); //default signal action @@ -829,12 +1016,17 @@ static void I_RegisterSignals (void) // If these defines don't exist, // then compilation would have failed above us... -#ifndef NEWSIGNALHANDLER +#if !defined(NEWSIGNALHANDLER) && !defined(USE_DBGHELP) signal(SIGILL , signal_handler); signal(SIGSEGV , signal_handler); signal(SIGABRT , signal_handler); signal(SIGFPE , signal_handler); #endif + +#ifdef USE_DBGHELP + // Initialize Windows SDK-specific crashdump handler (DbgHelp) + g_previous_toplevelexceptionfilter = SetUnhandledExceptionFilter(WriteMinidumpExceptionFilter); +#endif } #ifdef NEWSIGNALHANDLER @@ -1598,9 +1790,9 @@ static void I_Fork(void) { signum = WTERMSIG (status); #ifdef WCOREDUMP - I_ReportSignal(signum, WCOREDUMP (status)); + I_ReportSignal(signum, WCOREDUMP (status), NULL); #else - I_ReportSignal(signum, 0); + I_ReportSignal(signum, 0, NULL); #endif status = 128 + signum; } @@ -1656,7 +1848,7 @@ INT32 I_StartupSystem(void) // // I_Quit // -void I_Quit(void) +FUNCNORETURN void ATTRNORETURN I_Quit(void) { static SDL_bool quiting = SDL_FALSE; @@ -1732,7 +1924,7 @@ static boolean shutdowning = false; extern "C" consvar_t cv_fuzz; -void I_Error(const char *error, ...) +FUNCIERROR void ATTRNORETURN I_Error(const char *error, ...) { va_list argptr; char buffer[8192]; diff --git a/vcpkg.json b/vcpkg.json index 445e91e49..00a58c1c2 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -4,6 +4,10 @@ "version": "1.0.0", "builtin-baseline": "d5ec528843d29e3a52d745a64b469f810b2cedbf", "dependencies": [ + { + "name": "cpptrace", + "platform": "windows & !mingw" + }, "curl", "libogg", "libpng",