Commit 46c2b810 authored by Victor Stinner's avatar Victor Stinner Committed by GitHub

bpo-30125: Fix faulthandler.disable() on Windows (#1240)

* bpo-30125: Cleanup faulthandler.c

* Use size_t type for iterators
* Add { ... }

* bpo-30125: Fix faulthandler.disable() on Windows

On Windows, faulthandler.disable() now removes the exception handler
installed by faulthandler.enable().
parent 2a1aed04
...@@ -754,6 +754,18 @@ class FaultHandlerTests(unittest.TestCase): ...@@ -754,6 +754,18 @@ class FaultHandlerTests(unittest.TestCase):
3, 3,
name) name)
@unittest.skipUnless(MS_WINDOWS, 'specific to Windows')
def test_disable_windows_exc_handler(self):
code = dedent("""
import faulthandler
faulthandler.enable()
faulthandler.disable()
code = faulthandler._EXCEPTION_ACCESS_VIOLATION
faulthandler._raise_exception(code)
""")
output, exitcode = self.get_output(code)
self.assertEqual(output, [])
self.assertEqual(exitcode, 0xC0000005)
if __name__ == "__main__": if __name__ == "__main__":
......
...@@ -55,6 +55,9 @@ static struct { ...@@ -55,6 +55,9 @@ static struct {
int fd; int fd;
int all_threads; int all_threads;
PyInterpreterState *interp; PyInterpreterState *interp;
#ifdef MS_WINDOWS
void *exc_handler;
#endif
} fatal_error = {0, NULL, -1, 0}; } fatal_error = {0, NULL, -1, 0};
#ifdef FAULTHANDLER_LATER #ifdef FAULTHANDLER_LATER
...@@ -395,8 +398,7 @@ faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info) ...@@ -395,8 +398,7 @@ faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info)
if (code == EXCEPTION_ACCESS_VIOLATION) { if (code == EXCEPTION_ACCESS_VIOLATION) {
/* disable signal handler for SIGSEGV */ /* disable signal handler for SIGSEGV */
size_t i; for (size_t i=0; i < faulthandler_nsignals; i++) {
for (i=0; i < faulthandler_nsignals; i++) {
fault_handler_t *handler = &faulthandler_handlers[i]; fault_handler_t *handler = &faulthandler_handlers[i];
if (handler->signum == SIGSEGV) { if (handler->signum == SIGSEGV) {
faulthandler_disable_fatal_handler(handler); faulthandler_disable_fatal_handler(handler);
...@@ -418,14 +420,12 @@ faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info) ...@@ -418,14 +420,12 @@ faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info)
static int static int
faulthandler_enable(void) faulthandler_enable(void)
{ {
size_t i;
if (fatal_error.enabled) { if (fatal_error.enabled) {
return 0; return 0;
} }
fatal_error.enabled = 1; fatal_error.enabled = 1;
for (i=0; i < faulthandler_nsignals; i++) { for (size_t i=0; i < faulthandler_nsignals; i++) {
fault_handler_t *handler; fault_handler_t *handler;
#ifdef HAVE_SIGACTION #ifdef HAVE_SIGACTION
struct sigaction action; struct sigaction action;
...@@ -462,7 +462,8 @@ faulthandler_enable(void) ...@@ -462,7 +462,8 @@ faulthandler_enable(void)
} }
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
AddVectoredExceptionHandler(1, faulthandler_exc_handler); assert(fatal_error.exc_handler == NULL);
fatal_error.exc_handler = AddVectoredExceptionHandler(1, faulthandler_exc_handler);
#endif #endif
return 0; return 0;
} }
...@@ -504,17 +505,20 @@ faulthandler_py_enable(PyObject *self, PyObject *args, PyObject *kwargs) ...@@ -504,17 +505,20 @@ faulthandler_py_enable(PyObject *self, PyObject *args, PyObject *kwargs)
static void static void
faulthandler_disable(void) faulthandler_disable(void)
{ {
unsigned int i;
fault_handler_t *handler;
if (fatal_error.enabled) { if (fatal_error.enabled) {
fatal_error.enabled = 0; fatal_error.enabled = 0;
for (i=0; i < faulthandler_nsignals; i++) { for (size_t i=0; i < faulthandler_nsignals; i++) {
fault_handler_t *handler;
handler = &faulthandler_handlers[i]; handler = &faulthandler_handlers[i];
faulthandler_disable_fatal_handler(handler); faulthandler_disable_fatal_handler(handler);
} }
} }
#ifdef MS_WINDOWS
if (fatal_error.exc_handler != NULL) {
RemoveVectoredExceptionHandler(fatal_error.exc_handler);
fatal_error.exc_handler = NULL;
}
#endif
Py_CLEAR(fatal_error.file); Py_CLEAR(fatal_error.file);
} }
...@@ -777,9 +781,7 @@ faulthandler_user(int signum) ...@@ -777,9 +781,7 @@ faulthandler_user(int signum)
static int static int
check_signum(int signum) check_signum(int signum)
{ {
unsigned int i; for (size_t i=0; i < faulthandler_nsignals; i++) {
for (i=0; i < faulthandler_nsignals; i++) {
if (faulthandler_handlers[i].signum == signum) { if (faulthandler_handlers[i].signum == signum) {
PyErr_Format(PyExc_RuntimeError, PyErr_Format(PyExc_RuntimeError,
"signal %i cannot be registered, " "signal %i cannot be registered, "
...@@ -1122,16 +1124,12 @@ faulthandler_stack_overflow(PyObject *self) ...@@ -1122,16 +1124,12 @@ faulthandler_stack_overflow(PyObject *self)
static int static int
faulthandler_traverse(PyObject *module, visitproc visit, void *arg) faulthandler_traverse(PyObject *module, visitproc visit, void *arg)
{ {
#ifdef FAULTHANDLER_USER
unsigned int signum;
#endif
#ifdef FAULTHANDLER_LATER #ifdef FAULTHANDLER_LATER
Py_VISIT(thread.file); Py_VISIT(thread.file);
#endif #endif
#ifdef FAULTHANDLER_USER #ifdef FAULTHANDLER_USER
if (user_signals != NULL) { if (user_signals != NULL) {
for (signum=0; signum < NSIG; signum++) for (size_t signum=0; signum < NSIG; signum++)
Py_VISIT(user_signals[signum].file); Py_VISIT(user_signals[signum].file);
} }
#endif #endif
...@@ -1342,10 +1340,6 @@ int _PyFaulthandler_Init(void) ...@@ -1342,10 +1340,6 @@ int _PyFaulthandler_Init(void)
void _PyFaulthandler_Fini(void) void _PyFaulthandler_Fini(void)
{ {
#ifdef FAULTHANDLER_USER
unsigned int signum;
#endif
#ifdef FAULTHANDLER_LATER #ifdef FAULTHANDLER_LATER
/* later */ /* later */
if (thread.cancel_event) { if (thread.cancel_event) {
...@@ -1363,8 +1357,9 @@ void _PyFaulthandler_Fini(void) ...@@ -1363,8 +1357,9 @@ void _PyFaulthandler_Fini(void)
#ifdef FAULTHANDLER_USER #ifdef FAULTHANDLER_USER
/* user */ /* user */
if (user_signals != NULL) { if (user_signals != NULL) {
for (signum=0; signum < NSIG; signum++) for (size_t signum=0; signum < NSIG; signum++) {
faulthandler_unregister(&user_signals[signum], signum); faulthandler_unregister(&user_signals[signum], signum);
}
PyMem_Free(user_signals); PyMem_Free(user_signals);
user_signals = NULL; user_signals = NULL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment