I am extending a Python 2.7.5 app for Windows. The app uses SetUnhandledExceptionFilter to install a Python function that is called when an unhandled C exception occurs:
@ctypes.WINFUNCTYPE(ctypes.wintypes.LONG, PEXCEPTION_POINTERS)
def crashHandler(exceptionInfo):
# Some code that deals with the unhandled C exception...
...
windll.kernel32.SetUnhandledExceptionFilter(crashHandler)
(I will give the code for PEXCEPTION_POINTERS below because I don't think it's relevant for the purpose of this question.)
In its original form, crashHandler does some logging and shuts down the process. I have observed it deal with unhandled exceptions a few times, so I'm pretty confident that crashHandler is correctly installed as an UnhandledExceptionFilter.
I have made some modifications to crashHandler and would now like to test it. To do this, my idea would be to programmatically raise a C exception that should then be handled by crashHandler. I tried the following:
>>> windll.kernel32.RaiseException(5, 0, 0, None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
WindowsError: [Error 5] Access is denied
>>> windll.kernel32.RaiseException(6, 0, 0, None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
WindowsError: [Error 6] The handle is invalid
So the exception is immediately caught by the Python interpreter, hence does not get propagated to my crashHandler.
How can I either a) disable Python's exception handling or b) programmatically raise a C exception that is not caught by Python's exception handling mechanism and gets propagated to my crashHandler?
Here's the code for PEXCEPTION_POINTERS:
from ctypes import Structure
import ctypes
EXCEPTION_MAXIMUM_PARAMETERS = 15
class EXCEPTION_RECORD(Structure):
pass
PEXCEPTION_RECORD = ctypes.wintypes.POINTER(EXCEPTION_RECORD)
EXCEPTION_RECORD._fields_ = [
('ExceptionCode', ctypes.wintypes.DWORD),
('ExceptionFlags', ctypes.wintypes.DWORD),
('ExceptionRecord', PEXCEPTION_RECORD),
('ExceptionAddress', ctypes.wintypes.LPVOID),
('NumberParameters', ctypes.wintypes.DWORD),
('ExceptionInformation', ctypes.wintypes.LPVOID * EXCEPTION_MAXIMUM_PARAMETERS),
]
class EXCEPTION_POINTERS(Structure):
_fields_ = [('ExceptionRecord', PEXCEPTION_RECORD),
('ContextRecord', ctypes.wintypes.LPVOID)]
PEXCEPTION_POINTERS = ctypes.wintypes.POINTER(EXCEPTION_POINTERS)
crashHandler(the_arguments)? These things should all be mocked when doing unit-testing.