From 4b3bdc517277d5b4851a609184997b5215b87926 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 21 Apr 2017 17:14:21 +0200 Subject: [PATCH 1/2] bpo-30125: Cleanup faulthandler.c * Use size_t type for iterators * Add { ... } --- Modules/faulthandler.c | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index fc9490d0d44889..7feefb62077806 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -395,8 +395,7 @@ faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info) if (code == EXCEPTION_ACCESS_VIOLATION) { /* disable signal handler for SIGSEGV */ - size_t i; - for (i=0; i < faulthandler_nsignals; i++) { + for (size_t i=0; i < faulthandler_nsignals; i++) { fault_handler_t *handler = &faulthandler_handlers[i]; if (handler->signum == SIGSEGV) { faulthandler_disable_fatal_handler(handler); @@ -418,14 +417,12 @@ faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info) static int faulthandler_enable(void) { - size_t i; - if (fatal_error.enabled) { return 0; } fatal_error.enabled = 1; - for (i=0; i < faulthandler_nsignals; i++) { + for (size_t i=0; i < faulthandler_nsignals; i++) { fault_handler_t *handler; #ifdef HAVE_SIGACTION struct sigaction action; @@ -504,17 +501,14 @@ faulthandler_py_enable(PyObject *self, PyObject *args, PyObject *kwargs) static void faulthandler_disable(void) { - unsigned int i; - fault_handler_t *handler; - if (fatal_error.enabled) { 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]; faulthandler_disable_fatal_handler(handler); } } - Py_CLEAR(fatal_error.file); } @@ -777,9 +771,7 @@ faulthandler_user(int signum) static int check_signum(int signum) { - unsigned int i; - - for (i=0; i < faulthandler_nsignals; i++) { + for (size_t i=0; i < faulthandler_nsignals; i++) { if (faulthandler_handlers[i].signum == signum) { PyErr_Format(PyExc_RuntimeError, "signal %i cannot be registered, " @@ -1122,16 +1114,12 @@ faulthandler_stack_overflow(PyObject *self) static int faulthandler_traverse(PyObject *module, visitproc visit, void *arg) { -#ifdef FAULTHANDLER_USER - unsigned int signum; -#endif - #ifdef FAULTHANDLER_LATER Py_VISIT(thread.file); #endif #ifdef FAULTHANDLER_USER if (user_signals != NULL) { - for (signum=0; signum < NSIG; signum++) + for (size_t signum=0; signum < NSIG; signum++) Py_VISIT(user_signals[signum].file); } #endif @@ -1342,10 +1330,6 @@ int _PyFaulthandler_Init(void) void _PyFaulthandler_Fini(void) { -#ifdef FAULTHANDLER_USER - unsigned int signum; -#endif - #ifdef FAULTHANDLER_LATER /* later */ if (thread.cancel_event) { @@ -1363,8 +1347,9 @@ void _PyFaulthandler_Fini(void) #ifdef FAULTHANDLER_USER /* user */ if (user_signals != NULL) { - for (signum=0; signum < NSIG; signum++) + for (size_t signum=0; signum < NSIG; signum++) { faulthandler_unregister(&user_signals[signum], signum); + } PyMem_Free(user_signals); user_signals = NULL; } From dfa8dd3f89f4b443372c6f62114e2813dd092164 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 21 Apr 2017 17:18:42 +0200 Subject: [PATCH 2/2] bpo-30125: Fix faulthandler.disable() on Windows On Windows, faulthandler.disable() now removes the exception handler installed by faulthandler.enable(). --- Lib/test/test_faulthandler.py | 12 ++++++++++++ Modules/faulthandler.c | 12 +++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py index 28dd5f4e98f938..626e2458dcd9a6 100644 --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -754,6 +754,18 @@ def test_raise_exception(self): 3, 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__": diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index 7feefb62077806..dcfebf2781f6c9 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -55,6 +55,9 @@ static struct { int fd; int all_threads; PyInterpreterState *interp; +#ifdef MS_WINDOWS + void *exc_handler; +#endif } fatal_error = {0, NULL, -1, 0}; #ifdef FAULTHANDLER_LATER @@ -459,7 +462,8 @@ faulthandler_enable(void) } #ifdef MS_WINDOWS - AddVectoredExceptionHandler(1, faulthandler_exc_handler); + assert(fatal_error.exc_handler == NULL); + fatal_error.exc_handler = AddVectoredExceptionHandler(1, faulthandler_exc_handler); #endif return 0; } @@ -509,6 +513,12 @@ faulthandler_disable(void) 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); }