After a lot of research, coupled with a lack of knowledge in Windows, I finally reached a working solution that automatically sets completion functions for new threads.
The trick is to create a dll to handle your failures / exceptions. Your dll implements the reserved DllMain() function. This function receives notifications every time a new thread or process joins the main process. The fdwReason parameter contains information about the event.
- New thread:
DLL_THREAD_ATTACH - New process:
DLL_PROCESS_ATTACH
Deploy the completion handlers in the dll and call signal() and std::set_terminate() for each thread or process that is running.
BOOL WINAPI DllMain( _In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved) { if (fdwReason==DLL_THREAD_ATTACH) { signal(SIGSEGV, seg_handler); std::set_terminate( std_handler ); } if (fdwReason==DLL_PROCESS_ATTACH) { signal(SIGSEGV, seg_handler); std::set_terminate( std_handler ); } return TRUE; }
My handlers look like this:
#include <windows.h> #include "StackWalker.h" #include <signal.h> #include <DbgHelp.h> #include <iostream> #include <qdebug.h> void seg_handler(int sig) { // Simple callstack unsigned int i; void * stack[ 100 ]; unsigned short frames; SYMBOL_INFO * symbol; HANDLE process; process = GetCurrentProcess(); SymInitialize( process, NULL, TRUE ); frames = CaptureStackBackTrace( 0, 100, stack, NULL ); symbol = ( SYMBOL_INFO * )calloc( sizeof( SYMBOL_INFO ) + 256 * sizeof( char ), 1 ); symbol->MaxNameLen = 255; symbol->SizeOfStruct = sizeof( SYMBOL_INFO ); for( i = 0; i < frames; i++ ) { SymFromAddr( process, ( DWORD64 )( stack[ i ] ), 0, symbol ); printf( "%i: %s - 0x%0X\n", frames - i - 1, symbol->Name, symbol->Address ); } free( symbol ); // Detailed callstack/crashinfo StackWalker sw; sw.ShowCallstack(GetCurrentThread()); exit(1); } void std_handler( void ) { seg_handler(1); }
Handlers above use StackWalker
Edit:
Of course, you also need to add completion handlers to your main thread:
int main(int argc, char *argv[]) { CALL_LOGGER(); signal(SIGSEGV, seg_handler); std::set_terminate( std_handler ); return runapp(argc, argv); }
Hope this helps someone
-Jakob