From db4d20317b654ea57c43204c08484478d0b390cd Mon Sep 17 00:00:00 2001 From: Matthew Parkinson Date: Wed, 14 Aug 2019 11:12:32 +0100 Subject: [PATCH] Handle exceptions and print stack traces. --- src/test/setup.h | 76 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/src/test/setup.h b/src/test/setup.h index 528d5c0a4..76d523027 100644 --- a/src/test/setup.h +++ b/src/test/setup.h @@ -1,19 +1,95 @@ #if defined(WIN32) && defined(SNMALLOC_CI_BUILD) # include +# include +# include # include # include +// Has to come after the PAL. +# include +# pragma comment(lib, "dbghelp.lib") + +void print_stack_trace() +{ + DWORD error; + HANDLE hProcess = GetCurrentProcess(); + + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; + + pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); + pSymbol->MaxNameLen = MAX_SYM_NAME; + + SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); + + if (!SymInitialize(hProcess, NULL, TRUE)) + { + // SymInitialize failed + error = GetLastError(); + printf("SymInitialize returned error : %d\n", error); + return; + } + + void* stack[1024]; + DWORD count = CaptureStackBackTrace(0, 1024, stack, NULL); + IMAGEHLP_LINE64 line; + line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); + + for (int i = 0; count > 0; count--, i++) + { + DWORD64 dwDisplacement = 0; + DWORD64 dwAddress = (DWORD64)stack[i]; + + if (SymFromAddr(hProcess, dwAddress, &dwDisplacement, pSymbol)) + { + DWORD dwDisplacement2 = 0; + if (SymGetLineFromAddr64(hProcess, dwAddress, &dwDisplacement2, &line)) + { + std::cerr << "Frame: " << pSymbol->Name << " (" << line.FileName << ": " + << line.LineNumber << ")" << std::endl; + } + else + { + std::cerr << "Frame: " << pSymbol->Name << std::endl; + } + } + else + { + error = GetLastError(); + std::cerr << "SymFromAddr returned error : " << error << std::endl; + } + } +} + void _cdecl error(int signal) { UNUSED(signal); puts("*****ABORT******"); + + print_stack_trace(); + + _exit(1); +} + +# define CALL_LAST 0 +LONG WINAPI VectoredHandler(struct _EXCEPTION_POINTERS* ExceptionInfo) +{ + UNUSED(ExceptionInfo); + + puts("*****UNHANDLED EXCEPTION******"); + + print_stack_trace(); + _exit(1); } + void setup() { // Disable abort dialog box in CI builds. _set_error_mode(_OUT_TO_STDERR); _set_abort_behavior(0, _WRITE_ABORT_MSG); signal(SIGABRT, error); + + AddVectoredExceptionHandler(CALL_LAST, VectoredHandler); } #else void setup() {}