Windows: Add stacktrace support when unhandled exception occurs.
authorAntony Riakiotakis <kalast@gmail.com>
Tue, 3 Mar 2015 12:39:15 +0000 (13:39 +0100)
committerAntony Riakiotakis <kalast@gmail.com>
Tue, 3 Mar 2015 12:39:15 +0000 (13:39 +0100)
We need to register the exception handler slightly differently here, as
well as adding DbgHelp as a library, but according to docs it should be
supported in recent Windows editions (Win XP included even).

We can try it first and revert if there are issues.

CMakeLists.txt
build_files/scons/config/win32-mingw-config.py
build_files/scons/config/win32-vc-config.py
build_files/scons/config/win64-mingw-config.py
build_files/scons/config/win64-vc-config.py
source/blender/blenlib/intern/system.c
source/creator/creator.c

index cdef12cb923c713288bda5b39791cd8bf6243008..e3fb9584749aef8e30ac1f65580fb2a63847735f 100644 (file)
@@ -1168,7 +1168,7 @@ elseif(WIN32)
                set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO")
                set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO")
 
-               list(APPEND PLATFORM_LINKLIBS ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32 advapi32 shfolder shell32 ole32 oleaut32 uuid psapi)
+               list(APPEND PLATFORM_LINKLIBS ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32 advapi32 shfolder shell32 ole32 oleaut32 uuid psapi Dbghelp)
 
                if(WITH_INPUT_IME)
                        list(APPEND PLATFORM_LINKLIBS imm32)
@@ -1541,7 +1541,7 @@ elseif(WIN32)
                        endif()
                endif()
                
-               list(APPEND PLATFORM_LINKLIBS -lshell32 -lshfolder -lgdi32 -lmsvcrt -lwinmm -lmingw32 -lm -lws2_32 -lz -lstdc++ -lole32 -luuid -lwsock32 -lpsapi)
+               list(APPEND PLATFORM_LINKLIBS -lshell32 -lshfolder -lgdi32 -lmsvcrt -lwinmm -lmingw32 -lm -lws2_32 -lz -lstdc++ -lole32 -luuid -lwsock32 -lpsapi -ldbghelp)
 
                if(WITH_INPUT_IME)
                        list(APPEND PLATFORM_LINKLIBS -limm32)
index 0fb84bfa4a5433b4cefeba5819d3cce5c5141162..87c35e179cb2f4d719968527e25cdfb5c0c5be8f 100644 (file)
@@ -198,7 +198,7 @@ C_WARN = ['-Wno-char-subscripts', '-Wdeclaration-after-statement', '-Wstrict-pro
 
 CC_WARN = [ '-Wall' ]
 
-LLIBS = ['-lshell32', '-lshfolder', '-lgdi32', '-lmsvcrt', '-lwinmm', '-lmingw32', '-lm', '-lws2_32', '-lz', '-lstdc++','-lole32','-luuid', '-lwsock32', '-lpsapi']
+LLIBS = ['-lshell32', '-lshfolder', '-lgdi32', '-lmsvcrt', '-lwinmm', '-lmingw32', '-lm', '-lws2_32', '-lz', '-lstdc++','-lole32','-luuid', '-lwsock32', '-lpsapi', '-ldbghelp']
 
 if WITH_BF_IME:
     LLIBS.append('-limm32')
index 8e66e931ee9452915969c4832f26ebd5fc5834a0..9f3b3440628f1deef2b5dc765316f7ffef6498ad 100644 (file)
@@ -237,7 +237,7 @@ C_WARN = []
 CC_WARN = []
 CXX_WARN = []
 
-LLIBS = ['ws2_32', 'vfw32', 'winmm', 'kernel32', 'user32', 'gdi32', 'comdlg32', 'advapi32', 'shfolder', 'shell32', 'ole32', 'oleaut32', 'uuid', 'psapi']
+LLIBS = ['ws2_32', 'vfw32', 'winmm', 'kernel32', 'user32', 'gdi32', 'comdlg32', 'advapi32', 'shfolder', 'shell32', 'ole32', 'oleaut32', 'uuid', 'psapi', 'Dbghelp']
 
 if WITH_BF_IME:
     LLIBS.append('imm32')
index ab39568df5507d890c2b38f3bdd0a80f911e658b..57eaae81d490ee61f1fb2a3f9d8e9f0545600b92 100644 (file)
@@ -193,7 +193,7 @@ C_WARN = ['-Wno-char-subscripts', '-Wdeclaration-after-statement', '-Wstrict-pro
 
 CC_WARN = [ '-Wall', '-Wno-char-subscripts' ]
 
-LLIBS = ['-lshell32', '-lshfolder', '-lgdi32', '-lmsvcrt', '-lwinmm', '-lmingw32', '-lm', '-lws2_32', '-lz', '-lstdc++','-lole32','-luuid', '-lwsock32', '-lpsapi', '-lpthread']
+LLIBS = ['-lshell32', '-lshfolder', '-lgdi32', '-lmsvcrt', '-lwinmm', '-lmingw32', '-lm', '-lws2_32', '-lz', '-lstdc++','-lole32','-luuid', '-lwsock32', '-lpsapi', '-lpthread', '-ldbghelp']
 
 if WITH_BF_IME:
     LLIBS.append('-limm32')
index 19e9667d597cac8323e5d0cff6a26534e76957e8..9ac0173537e8a4e003a52a17c3eb346eaf44acf5 100644 (file)
@@ -244,7 +244,7 @@ C_WARN = []
 CC_WARN = []
 CXX_WARN = []
 
-LLIBS = ['ws2_32', 'vfw32', 'winmm', 'kernel32', 'user32', 'gdi32', 'comdlg32', 'advapi32', 'shfolder', 'shell32', 'ole32', 'oleaut32', 'uuid', 'psapi']
+LLIBS = ['ws2_32', 'vfw32', 'winmm', 'kernel32', 'user32', 'gdi32', 'comdlg32', 'advapi32', 'shfolder', 'shell32', 'ole32', 'oleaut32', 'uuid', 'psapi', 'Dbghelp']
 
 if WITH_BF_IME:
     LLIBS.append('imm32')
index d83077e0e78a1fed1cce796f63ce9c87507f686c..b6b0f14a4e20f5f0790458f4aa271f3811925008 100644 (file)
 
 #include "BLI_system.h"
 
+#include "MEM_guardedalloc.h"
+
 /* for backtrace */
 #if defined(__linux__) || defined(__APPLE__)
 #  include <execinfo.h>
-#elif defined(_MSV_VER)
+#elif defined(WIN32)
+#  include <windows.h>
 #  include <DbgHelp.h>
 #endif
 
@@ -97,17 +100,18 @@ void BLI_system_backtrace(FILE *fp)
 #elif defined(_MSC_VER)
 
        (void)fp;
-#if 0
+#if defined WIN32
 #define MAXSYMBOL 256
-       unsigned short  i;
+#define SIZE 100
+       unsigned short i;
        void *stack[SIZE];
        unsigned short nframes;
-       SYMBOL_INFO     *symbolinfo;
+       SYMBOL_INFO *symbolinfo;
        HANDLE process;
 
        process = GetCurrentProcess();
 
-       SymInitialize(process, NULL, true);
+       SymInitialize(process, NULL, TRUE);
 
        nframes = CaptureStackBackTrace(0, SIZE, stack, NULL);
        symbolinfo = MEM_callocN(sizeof(SYMBOL_INFO) + MAXSYMBOL * sizeof(char), "crash Symbol table");
@@ -122,6 +126,7 @@ void BLI_system_backtrace(FILE *fp)
 
        MEM_freeN(symbolinfo);
 #undef MAXSYMBOL
+#undef SIZE
 #endif
 
        /* ------------------ */
index 4b523b66b040c5d4e1de40eb1bfb3273042afaca..547ca3f5ab511b82b669153c9239efe4621382f1 100644 (file)
@@ -597,6 +597,88 @@ static void blender_crash_handler(int signum)
 #endif
 }
 
+#ifdef WIN32
+LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS * ExceptionInfo)
+{
+  switch(ExceptionInfo->ExceptionRecord->ExceptionCode)
+  {
+    case EXCEPTION_ACCESS_VIOLATION:
+      fputs("Error: EXCEPTION_ACCESS_VIOLATION\n", stderr);
+      break;
+    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+      fputs("Error: EXCEPTION_ARRAY_BOUNDS_EXCEEDED\n", stderr);
+      break;
+    case EXCEPTION_BREAKPOINT:
+      fputs("Error: EXCEPTION_BREAKPOINT\n", stderr);
+      break;
+    case EXCEPTION_DATATYPE_MISALIGNMENT:
+      fputs("Error: EXCEPTION_DATATYPE_MISALIGNMENT\n", stderr);
+      break;
+    case EXCEPTION_FLT_DENORMAL_OPERAND:
+      fputs("Error: EXCEPTION_FLT_DENORMAL_OPERAND\n", stderr);
+      break;
+    case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+      fputs("Error: EXCEPTION_FLT_DIVIDE_BY_ZERO\n", stderr);
+      break;
+    case EXCEPTION_FLT_INEXACT_RESULT:
+      fputs("Error: EXCEPTION_FLT_INEXACT_RESULT\n", stderr);
+      break;
+    case EXCEPTION_FLT_INVALID_OPERATION:
+      fputs("Error: EXCEPTION_FLT_INVALID_OPERATION\n", stderr);
+      break;
+    case EXCEPTION_FLT_OVERFLOW:
+      fputs("Error: EXCEPTION_FLT_OVERFLOW\n", stderr);
+      break;
+    case EXCEPTION_FLT_STACK_CHECK:
+      fputs("Error: EXCEPTION_FLT_STACK_CHECK\n", stderr);
+      break;
+    case EXCEPTION_FLT_UNDERFLOW:
+      fputs("Error: EXCEPTION_FLT_UNDERFLOW\n", stderr);
+      break;
+    case EXCEPTION_ILLEGAL_INSTRUCTION:
+      fputs("Error: EXCEPTION_ILLEGAL_INSTRUCTION\n", stderr);
+      break;
+    case EXCEPTION_IN_PAGE_ERROR:
+      fputs("Error: EXCEPTION_IN_PAGE_ERROR\n", stderr);
+      break;
+    case EXCEPTION_INT_DIVIDE_BY_ZERO:
+      fputs("Error: EXCEPTION_INT_DIVIDE_BY_ZERO\n", stderr);
+      break;
+    case EXCEPTION_INT_OVERFLOW:
+      fputs("Error: EXCEPTION_INT_OVERFLOW\n", stderr);
+      break;
+    case EXCEPTION_INVALID_DISPOSITION:
+      fputs("Error: EXCEPTION_INVALID_DISPOSITION\n", stderr);
+      break;
+    case EXCEPTION_NONCONTINUABLE_EXCEPTION:
+      fputs("Error: EXCEPTION_NONCONTINUABLE_EXCEPTION\n", stderr);
+      break;
+    case EXCEPTION_PRIV_INSTRUCTION:
+      fputs("Error: EXCEPTION_PRIV_INSTRUCTION\n", stderr);
+      break;
+    case EXCEPTION_SINGLE_STEP:
+      fputs("Error: EXCEPTION_SINGLE_STEP\n", stderr);
+      break;
+    case EXCEPTION_STACK_OVERFLOW:
+      fputs("Error: EXCEPTION_STACK_OVERFLOW\n", stderr);
+      break;
+    default:
+      fputs("Error: Unrecognized Exception\n", stderr);
+      break;
+  }
+  fflush(stderr);
+  /* If this is a stack overflow then we can't walk the stack, so just show
+   * where the error happened */
+  if (EXCEPTION_STACK_OVERFLOW != ExceptionInfo->ExceptionRecord->ExceptionCode)
+  {
+         blender_crash_handler(SIGSEGV);
+  }
+
+  return EXCEPTION_EXECUTE_HANDLER;
+}
+#endif
+
+
 static void blender_abort_handler(int UNUSED(signum))
 {
        /* Delete content of temp dir! */
@@ -1624,13 +1706,18 @@ int main(
        BLI_argsParse(ba, 1, NULL, NULL);
 
        if (use_crash_handler) {
+#ifdef WIN32
+               SetUnhandledExceptionFilter(windows_exception_handler);
+#else
                /* after parsing args */
                signal(SIGSEGV, blender_crash_handler);
+#endif
        }
 
        if (use_abort_handler) {
                signal(SIGABRT, blender_abort_handler);
        }
+
 #else
        G.factory_startup = true;  /* using preferences or user startup makes no sense for py-as-module */
        (void)syshandle;