What actions do I need to take to get a crash dump in ALL error scenarios?
I use exactly the ones you've listed, plus _set_purecall_handler
, plus this handy snippet of code:
void EnableCrashingOnCrashes(){ typedef BOOL (WINAPI *tGetPolicy)(LPDWORD lpFlags); typedef BOOL (WINAPI *tSetPolicy)(DWORD dwFlags); static const DWORD EXCEPTION_SWALLOWING = 0x1; const HMODULE kernel32 = LoadLibraryA("kernel32.dll"); const tGetPolicy pGetPolicy = (tGetPolicy)GetProcAddress(kernel32, "GetProcessUserModeExceptionPolicy"); const tSetPolicy pSetPolicy = (tSetPolicy)GetProcAddress(kernel32, "SetProcessUserModeExceptionPolicy"); if(pGetPolicy && pSetPolicy) { DWORD dwFlags; if(pGetPolicy(&dwFlags)) { // Turn off the filter pSetPolicy(dwFlags & ~EXCEPTION_SWALLOWING); } }}
Source:http://randomascii.wordpress.com/2012/07/05/when-even-crashing-doesnt-work/
These other articles on his site also helped me understand this:http://randomascii.wordpress.com/2011/12/07/increased-reliability-through-more-crashes/http://randomascii.wordpress.com/2012/07/22/more-adventures-in-failing-to-crash-properly/
SetUnhandledExceptionFilter is emphatically not enough to capture all unexpected exits. If an application accidentally calls a pure virtual function then a dialog will pop up. The application will hang, but not crash. Since there is no exception neither SetUnhandledExceptionFilter nor WER can help. There are a few variations on this theme.
Worse yet is the weirdness if you crash in a kernel callback such as a WindowProc. If this happens in a 32-bit application on 64-bit Windows then the exception is caught by the OS and execution continues. Yes, the crash is silently handed. I find that terrifying.
http://randomascii.wordpress.com/2012/07/05/when-even-crashing-doesnt-work/ should detail all of the tricks needed to handle these unusual cases.
Tall order, just in brief:
- You need not to use any other
_set*
functions,SetUnhandledExceptionFilter
is enough for all. - C runtime functions like
abort
will disable the global exception handler, which you setup usingSetUnhandledExceptionFilter
. CRT will simply call this same function willNULL
parameter, and your exception-handler is disabled (not called), if CRT is causing crash! What you can do? [X] - Disable all other running threads when the excption-handler gets called. Just lookup all threads using
CreateToolhelp32Snapshot
, and other functions. Look for this process, and suspend all other running threads (except current, ofcourse). - Use SEH or no-SEH, global-exception handler gets called unless CRT interfers. Not to worry (in MOST cases).
- Do not any CLR in-between, it will not allow the exception handler to call, if any CLR/managed call (yes from C/C++) comes in between.
- You cannot handle one exception - Stack Overflow! Think! Running under a debugger is only solution, see below.
There is more to it, which I haven't tried (not found usefulness) - Vectored Exception Handling.
One other approach is to run the application into a debugger, which you can craft yourself! In the debugger, you can catch ALL exceptions, just like VS debugger catches. See my article. But, you know, this is not proper approach.
EDIT: Just read the last content about process-termination. You shouldn't control that. In any case, you can just hook the required APIs, which would act as what you code for (like displaying message box).
[X] You need to use API hooking. I dont have link and details handy. You'd hook other related APIs, but primarily the SetUnhandledExceptionFilter
(after you'd called it for you). You dummy (hooked) function will look like:
xxx SetUnhandledExceptionFilter_DUMMY(xxx){ // Dont do any thing return NULL;}
I dont have link and details of API hooking handy.
And why not attempt to make your application more safe?
- Correct all warnings (yes, even level 4).
- Use static analysis. VS itself has (in higher versions, though. Except 2012 - all variants have). Other SA tools are available.
- Do careful code-reviewing. It pays!
- Run and Debug your RELEASE build from the debugger. Use all features.
- Look and correct all possible memory leaks.
- Use defensive approach to programming. Rather than checking if null, defend it using ASSERT, or your own assert. Pack it with assertion, log, return from function.