From d727e23243ab5479b03aab1f924ca7ec0bccbcb6 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 1 Apr 2011 12:13:55 +0200 Subject: [PATCH] Issue #11393: The fault handler handles also SIGABRT --- Doc/library/faulthandler.rst | 14 +++++++------- Doc/using/cmdline.rst | 5 +++-- Lib/test/test_faulthandler.py | 9 +++++++++ Modules/faulthandler.c | 33 +++++++++++++++++++++++++-------- Python/pythonrun.c | 1 + 5 files changed, 45 insertions(+), 17 deletions(-) diff --git a/Doc/library/faulthandler.rst b/Doc/library/faulthandler.rst index 7b106bc68b7..106da45b4ce 100644 --- a/Doc/library/faulthandler.rst +++ b/Doc/library/faulthandler.rst @@ -6,10 +6,10 @@ This module contains functions to dump the Python traceback explicitly, on a fault, after a timeout or on a user signal. Call :func:`faulthandler.enable` to -install fault handlers for :const:`SIGSEGV`, :const:`SIGFPE`, :const:`SIGBUS` -and :const:`SIGILL` signals. You can also enable them at startup by setting the -:envvar:`PYTHONFAULTHANDLER` environment variable or by using :option:`-X` -``faulthandler`` command line option. +install fault handlers for :const:`SIGSEGV`, :const:`SIGFPE`, :const:`SIGABRT`, +:const:`SIGBUS` and :const:`SIGILL` signals. You can also enable them at +startup by setting the :envvar:`PYTHONFAULTHANDLER` environment variable or by +using :option:`-X` ``faulthandler`` command line option. The fault handler is compatible with system fault handlers like Apport or the Windows fault handler. The module uses an alternative stack for signal @@ -48,9 +48,9 @@ Fault handler state .. function:: enable(file=sys.stderr, all_threads=False) Enable the fault handler: install handlers for :const:`SIGSEGV`, - :const:`SIGFPE`, :const:`SIGBUS` and :const:`SIGILL` signals to dump the - Python traceback. It dumps the traceback of the current thread, or all - threads if *all_threads* is ``True``, into *file*. + :const:`SIGFPE`, :const:`SIGABRT`, :const:`SIGBUS` and :const:`SIGILL` + signals to dump the Python traceback. It dumps the traceback of the current + thread, or all threads if *all_threads* is ``True``, into *file*. .. function:: disable() diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 8a5a66278db..72b77cd3b95 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -502,8 +502,9 @@ These environment variables influence Python's behavior. If this environment variable is set, :func:`faulthandler.enable` is called at startup: install a handler for :const:`SIGSEGV`, :const:`SIGFPE`, - :const:`SIGBUS` and :const:`SIGILL` signals to dump the Python traceback. - This is equivalent to :option:`-X` ``faulthandler`` option. + :const:`SIGABRT`, :const:`SIGBUS` and :const:`SIGILL` signals to dump the + Python traceback. This is equivalent to :option:`-X` ``faulthandler`` + option. Debug-mode variables diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py index f26269c7bd4..1a79c506561 100644 --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -112,6 +112,15 @@ faulthandler._sigsegv() 3, 'Segmentation fault') + def test_sigabrt(self): + self.check_fatal_error(""" +import faulthandler +faulthandler.enable() +faulthandler._sigabrt() +""".strip(), + 3, + 'Aborted') + @unittest.skipIf(sys.platform == 'win32', "SIGFPE cannot be caught on Windows") def test_sigfpe(self): diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index 5ec94f0a9fb..abff79e434d 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -10,9 +10,9 @@ #endif #ifndef MS_WINDOWS - /* register() is useless on Windows, because only SIGSEGV and SIGILL can be - handled by the process, and these signals can only be used with enable(), - not using register() */ + /* register() is useless on Windows, because only SIGSEGV, SIGABRT and + SIGILL can be handled by the process, and these signals can only be used + with enable(), not using register() */ # define FAULTHANDLER_USER #endif @@ -96,6 +96,7 @@ static fault_handler_t faulthandler_handlers[] = { {SIGILL, 0, "Illegal instruction", }, #endif {SIGFPE, 0, "Floating point exception", }, + {SIGABRT, 0, "Aborted", }, /* define SIGSEGV at the end to make it the default choice if searching the handler fails in faulthandler_fatal_error() */ {SIGSEGV, 0, "Segmentation fault", } @@ -202,7 +203,7 @@ faulthandler_dump_traceback_py(PyObject *self, } -/* Handler of SIGSEGV, SIGFPE, SIGBUS and SIGILL signals. +/* Handler of SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL signals. Display the current Python traceback, restore the previous handler and call the previous handler. @@ -253,9 +254,9 @@ faulthandler_fatal_error( PUTS(fd, handler->name); PUTS(fd, "\n\n"); - /* SIGSEGV, SIGFPE, SIGBUS and SIGILL are synchronous signals and so are - delivered to the thread that caused the fault. Get the Python thread - state of the current thread. + /* SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals and + so are delivered to the thread that caused the fault. Get the Python + thread state of the current thread. PyThreadState_Get() doesn't give the state of the thread that caused the fault if the thread released the GIL, and so this function cannot be @@ -282,7 +283,7 @@ faulthandler_fatal_error( raise(signum); } -/* Install handler for fatal signals (SIGSEGV, SIGFPE, ...). */ +/* Install the handler for fatal signals, faulthandler_fatal_error(). */ static PyObject* faulthandler_enable(PyObject *self, PyObject *args, PyObject *kwargs) @@ -714,6 +715,20 @@ faulthandler_sigfpe(PyObject *self, PyObject *args) Py_RETURN_NONE; } +static PyObject * +faulthandler_sigabrt(PyObject *self, PyObject *args) +{ +#if _MSC_VER + /* If Python is compiled in debug mode with Visual Studio, abort() opens + a popup asking the user how to handle the assertion. Use raise(SIGABRT) + instead. */ + raise(SIGABRT); +#else + abort(); +#endif + Py_RETURN_NONE; +} + #ifdef SIGBUS static PyObject * faulthandler_sigbus(PyObject *self, PyObject *args) @@ -847,6 +862,8 @@ static PyMethodDef module_methods[] = { "a SIGSEGV or SIGBUS signal depending on the platform")}, {"_sigsegv", faulthandler_sigsegv, METH_VARARGS, PyDoc_STR("_sigsegv(): raise a SIGSEGV signal")}, + {"_sigabrt", faulthandler_sigabrt, METH_VARARGS, + PyDoc_STR("_sigabrt(): raise a SIGABRT signal")}, {"_sigfpe", (PyCFunction)faulthandler_sigfpe, METH_NOARGS, PyDoc_STR("_sigfpe(): raise a SIGFPE signal")}, #ifdef SIGBUS diff --git a/Python/pythonrun.c b/Python/pythonrun.c index f787a4f8b37..1c36e63ac46 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -2124,6 +2124,7 @@ Py_FatalError(const char *msg) fflush(stderr); _Py_DumpTraceback(fd, tstate); } + _PyFaulthandler_Fini(); } #ifdef MS_WINDOWS