Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Raise unhandled C exception in Python

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)
like image 716
Michael Herrmann Avatar asked Feb 20 '26 13:02

Michael Herrmann


1 Answers

The windll module automatically catches windows SEH exceptions which occur in calls, and converts them to WindowsError python exceptions. Hence they are not unhandled exceptions.

You need to use an API which doesn't have such a good wrapper.

Your best bet is to use a C extension module which causes an access violation by dereferencing a random pointer (or null).

like image 124
Ben Avatar answered Feb 23 '26 01:02

Ben



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!