From 43f102271dd3dc64b167ee305be5061976bd41d6 Mon Sep 17 00:00:00 2001 From: kwolekr Date: Sun, 1 Feb 2015 03:08:04 -0500 Subject: [PATCH] Create minidump on fatal Win32 exceptions Remove software exception translator function, simplifying exception handler macros. FatalSystemExceptions are left unhandled. --- src/CMakeLists.txt | 5 +- src/debug.cpp | 160 ++++++++++++++++++++++++++++++++++++--------- src/debug.h | 44 ++++--------- src/exceptions.h | 6 -- src/main.cpp | 2 + src/porting.h | 4 ++ 6 files changed, 149 insertions(+), 72 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 848eb8d3..93083f36 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -128,6 +128,7 @@ add_definitions ( -DUSE_CMAKE_CONFIG_H ) if(WIN32) # Windows if(MSVC) # MSVC Specifics + set(PLATFORM_LIBS dbghelp.lib ${PLATFORM_LIBS}) # Surpress some useless warnings add_definitions ( /D "_CRT_SECURE_NO_DEPRECATE" /W1 ) else() # Probably MinGW = GCC @@ -630,11 +631,11 @@ if(MSVC) #set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/LTCG /NODEFAULTLIB:\"libcmtd.lib\" /NODEFAULTLIB:\"libcmt.lib\"") set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/LTCG") - set(CMAKE_CXX_FLAGS_SEMIDEBUG "/MDd /Zi /Ob0 /O1 /RTC1 /Wall") + set(CMAKE_CXX_FLAGS_SEMIDEBUG "/MDd /Zi /Ob0 /O1 /RTC1") # Debug build doesn't catch exceptions by itself # Add some optimizations because otherwise it's VERY slow - set(CMAKE_CXX_FLAGS_DEBUG "/MDd /Zi /Ob0 /Od /RTC1 /Wall") + set(CMAKE_CXX_FLAGS_DEBUG "/MDd /Zi /Ob0 /Od /RTC1") # Flags for C files (sqlite) # /MT = Link statically with standard library stuff diff --git a/src/debug.cpp b/src/debug.cpp index 3b2fb641..bd970a8e 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -29,6 +29,13 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "jthread/jmutex.h" #include "jthread/jmutexautolock.h" #include "config.h" + +#ifdef _MSC_VER + #include + #include "version.h" + #include "filesys.h" +#endif + /* Debug output */ @@ -57,7 +64,7 @@ void debugstreams_init(bool disable_stderr, const char *filename) if(filename) g_debugstreams[1] = fopen(filename, "a"); - + if(g_debugstreams[1]) { fprintf(g_debugstreams[1], "\n\n-------------\n"); @@ -91,7 +98,7 @@ public: //TODO: Is this slow? fflush(g_debugstreams[i]); } - + return c; } std::streamsize xsputn(const char *s, std::streamsize n) @@ -111,7 +118,7 @@ public: return n; } - + private: bool m_disable_stderr; }; @@ -133,7 +140,7 @@ void assert_fail(const char *assertion, const char *file, "%s:%u: %s: Assertion '%s' failed.\n", (unsigned long)get_current_thread_id(), file, line, function, assertion); - + debug_stacks_print(); if(g_debugstreams[1]) @@ -151,7 +158,7 @@ struct DebugStack DebugStack(threadid_t id); void print(FILE *file, bool everything); void print(std::ostream &os, bool everything); - + threadid_t threadid; char stack[DEBUG_STACK_SIZE][DEBUG_STACK_TEXT_SIZE]; int stack_i; // Points to the lowest empty position @@ -285,10 +292,10 @@ DebugStacker::DebugStacker(const char *text) DebugStacker::~DebugStacker() { JMutexAutoLock lock(g_debug_stacks_mutex); - + if(m_overflowed == true) return; - + m_stack->stack_i--; if(m_stack->stack_i == 0) @@ -301,35 +308,124 @@ DebugStacker::~DebugStacker() } } - #ifdef _MSC_VER -#if CATCH_UNHANDLED_EXCEPTIONS == 1 -void se_trans_func(unsigned int u, EXCEPTION_POINTERS* pExp) + +const char *Win32ExceptionCodeToString(DWORD exception_code) { - dstream<<"In trans_func.\n"; - if(u == EXCEPTION_ACCESS_VIOLATION) - { - PEXCEPTION_RECORD r = pExp->ExceptionRecord; - dstream<<"Access violation at "<ExceptionAddress - <<" write?="<ExceptionInformation[0] - <<" address="<ExceptionInformation[1] - <ExceptionRecord->ExceptionCode; + _snprintf(buf, sizeof(buf), + " >> === FATAL ERROR ===\n" + " >> %s (Exception 0x%08X) at 0x%p\n", + Win32ExceptionCodeToString(excode), excode, + pExceptInfo->ExceptionRecord->ExceptionAddress); + dstream << buf; + + if (minidump_created) + dstream << " >> Saved dump to " << dumpfile << std::endl; + else + dstream << " >> Failed to save dump" << std::endl; + + return EXCEPTION_EXECUTE_HANDLER; +} + #endif - +void debug_set_exception_handler() +{ +#ifdef _MSC_VER + SetUnhandledExceptionFilter(Win32ExceptionHandler); +#endif +} diff --git a/src/debug.h b/src/debug.h index ba2e8704..1027fde6 100644 --- a/src/debug.h +++ b/src/debug.h @@ -95,6 +95,8 @@ __NORETURN extern void assert_fail( #define assert(expr) ASSERT(expr) +void debug_set_exception_handler(); + /* DebugStack */ @@ -118,13 +120,12 @@ private: bool m_overflowed; }; -#define DSTACK(msg)\ +#define DSTACK(msg) \ DebugStacker __debug_stacker(msg); -#define DSTACKF(...)\ - char __buf[DEBUG_STACK_TEXT_SIZE];\ - snprintf(__buf,\ - DEBUG_STACK_TEXT_SIZE, __VA_ARGS__);\ +#define DSTACKF(...) \ + char __buf[DEBUG_STACK_TEXT_SIZE]; \ + snprintf(__buf, DEBUG_STACK_TEXT_SIZE, __VA_ARGS__); \ DebugStacker __debug_stacker(__buf); /* @@ -132,34 +133,13 @@ private: */ #if CATCH_UNHANDLED_EXCEPTIONS == 1 - #define BEGIN_PORTABLE_DEBUG_EXCEPTION_HANDLER try{ - #define END_PORTABLE_DEBUG_EXCEPTION_HANDLER(logstream)\ - }catch(std::exception &e){\ - logstream<<"ERROR: An unhandled exception occurred: "\ - <