I’m trying to write a test suite for a compiler (LLVM) and it works perfectly fine on every platform except for Windows. On Windows I get the “critical-error-handler” message box which stops the tests indefinitely.
This problem makes it very difficult to test because, with compilers, a problem often means invalid code on the assembly level, and thus crazy, unpredictable errors.
I found During a subprocess call, catch critical windows errors in Python instead of letting the OS handle it by showing nasty error pop-ups while searching for the answer, but this doesn’t work for me. I still get the message boxes when testing.
The documentation on [SetErrorMode](http://msdn.microsoft.com/en-us/library/ms680621(VS100).aspx) Says that:
SEM_FAILCRITICALERRORS:
The system does not display the critical-error-handler message box. Instead, the system sends the error to the calling process.SEM_NOGPFAULTERRORBOX:
The system does not display the Windows Error Reporting dialog.Each process has an associated error mode that indicates to the system how the application is going to respond to serious errors. A child process inherits the error mode of its parent process.
However, after calling SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX) and launching the process with CreateProcess with dwCreationFlags = CREATE_NEW_CONSOLE, I still get the boxes when subprocesses fail.
In case it matters, the exact Python code I am using is:
import ctypes
# 3 is SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX
ctypes.windll.kernel32.SetErrorMode(3)
How do I fix it?
The problem was actually Dr. Watson(link redacted), who rudely ignores SetErrorMode(link redacted). The only way to prevent Dr. Watson from stealing your joy is to prevent him from ever getting the call. There are two ways to do this.
Call
SetUnhandledExceptionHandler(yourexceptionhandler);If you call
exitin this handler, the program terminates normally and Dr. Watson is never invoked.This only works if you have access to the source code and feel like modifying it. In my case I had access to the source code, but it was a collection of a few hundred separate files, and so adding this code in all of them was a non starter. It also wouldn’t handle the case of an error before main, or just plain invalid executables.
Run the process under a debugger using
CreateProcess(..., DEBUG_PROCESS, ...)(link redacted) andWaitForDebugEvent(link redacted)When running a process like this, all exceptions are propagated to the debugger, and thus they can be handled appropriately.
This is a rather complex solution to what should be a simple problem, but it is the only way I have found to completely block Dr. Watson. I am Currently writing a minimal program that tries to run the subprocess normally in every way except for catching unhandled exceptions. I will post a link here once it is committed.