Commit d727e232 authored by Victor Stinner's avatar Victor Stinner

Issue #11393: The fault handler handles also SIGABRT

parent bc6a4db6
...@@ -6,10 +6,10 @@ ...@@ -6,10 +6,10 @@
This module contains functions to dump the Python traceback explicitly, on a 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 fault, after a timeout or on a user signal. Call :func:`faulthandler.enable` to
install fault handlers for :const:`SIGSEGV`, :const:`SIGFPE`, :const:`SIGBUS` install fault handlers for :const:`SIGSEGV`, :const:`SIGFPE`, :const:`SIGABRT`,
and :const:`SIGILL` signals. You can also enable them at startup by setting the :const:`SIGBUS` and :const:`SIGILL` signals. You can also enable them at
:envvar:`PYTHONFAULTHANDLER` environment variable or by using :option:`-X` startup by setting the :envvar:`PYTHONFAULTHANDLER` environment variable or by
``faulthandler`` command line option. using :option:`-X` ``faulthandler`` command line option.
The fault handler is compatible with system fault handlers like Apport or The fault handler is compatible with system fault handlers like Apport or
the Windows fault handler. The module uses an alternative stack for signal the Windows fault handler. The module uses an alternative stack for signal
...@@ -48,9 +48,9 @@ Fault handler state ...@@ -48,9 +48,9 @@ Fault handler state
.. function:: enable(file=sys.stderr, all_threads=False) .. function:: enable(file=sys.stderr, all_threads=False)
Enable the fault handler: install handlers for :const:`SIGSEGV`, Enable the fault handler: install handlers for :const:`SIGSEGV`,
:const:`SIGFPE`, :const:`SIGBUS` and :const:`SIGILL` signals to dump the :const:`SIGFPE`, :const:`SIGABRT`, :const:`SIGBUS` and :const:`SIGILL`
Python traceback. It dumps the traceback of the current thread, or all signals to dump the Python traceback. It dumps the traceback of the current
threads if *all_threads* is ``True``, into *file*. thread, or all threads if *all_threads* is ``True``, into *file*.
.. function:: disable() .. function:: disable()
......
...@@ -502,8 +502,9 @@ These environment variables influence Python's behavior. ...@@ -502,8 +502,9 @@ These environment variables influence Python's behavior.
If this environment variable is set, :func:`faulthandler.enable` is called If this environment variable is set, :func:`faulthandler.enable` is called
at startup: install a handler for :const:`SIGSEGV`, :const:`SIGFPE`, at startup: install a handler for :const:`SIGSEGV`, :const:`SIGFPE`,
:const:`SIGBUS` and :const:`SIGILL` signals to dump the Python traceback. :const:`SIGABRT`, :const:`SIGBUS` and :const:`SIGILL` signals to dump the
This is equivalent to :option:`-X` ``faulthandler`` option. Python traceback. This is equivalent to :option:`-X` ``faulthandler``
option.
Debug-mode variables Debug-mode variables
......
...@@ -112,6 +112,15 @@ faulthandler._sigsegv() ...@@ -112,6 +112,15 @@ faulthandler._sigsegv()
3, 3,
'Segmentation fault') 'Segmentation fault')
def test_sigabrt(self):
self.check_fatal_error("""
import faulthandler
faulthandler.enable()
faulthandler._sigabrt()
""".strip(),
3,
'Aborted')
@unittest.skipIf(sys.platform == 'win32', @unittest.skipIf(sys.platform == 'win32',
"SIGFPE cannot be caught on Windows") "SIGFPE cannot be caught on Windows")
def test_sigfpe(self): def test_sigfpe(self):
......
...@@ -10,9 +10,9 @@ ...@@ -10,9 +10,9 @@
#endif #endif
#ifndef MS_WINDOWS #ifndef MS_WINDOWS
/* register() is useless on Windows, because only SIGSEGV and SIGILL can be /* register() is useless on Windows, because only SIGSEGV, SIGABRT and
handled by the process, and these signals can only be used with enable(), SIGILL can be handled by the process, and these signals can only be used
not using register() */ with enable(), not using register() */
# define FAULTHANDLER_USER # define FAULTHANDLER_USER
#endif #endif
...@@ -96,6 +96,7 @@ static fault_handler_t faulthandler_handlers[] = { ...@@ -96,6 +96,7 @@ static fault_handler_t faulthandler_handlers[] = {
{SIGILL, 0, "Illegal instruction", }, {SIGILL, 0, "Illegal instruction", },
#endif #endif
{SIGFPE, 0, "Floating point exception", }, {SIGFPE, 0, "Floating point exception", },
{SIGABRT, 0, "Aborted", },
/* define SIGSEGV at the end to make it the default choice if searching the /* define SIGSEGV at the end to make it the default choice if searching the
handler fails in faulthandler_fatal_error() */ handler fails in faulthandler_fatal_error() */
{SIGSEGV, 0, "Segmentation fault", } {SIGSEGV, 0, "Segmentation fault", }
...@@ -202,7 +203,7 @@ faulthandler_dump_traceback_py(PyObject *self, ...@@ -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 Display the current Python traceback, restore the previous handler and call
the previous handler. the previous handler.
...@@ -253,9 +254,9 @@ faulthandler_fatal_error( ...@@ -253,9 +254,9 @@ faulthandler_fatal_error(
PUTS(fd, handler->name); PUTS(fd, handler->name);
PUTS(fd, "\n\n"); PUTS(fd, "\n\n");
/* SIGSEGV, SIGFPE, SIGBUS and SIGILL are synchronous signals and so are /* SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals and
delivered to the thread that caused the fault. Get the Python thread so are delivered to the thread that caused the fault. Get the Python
state of the current thread. thread state of the current thread.
PyThreadState_Get() doesn't give the state of the thread that caused the 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 fault if the thread released the GIL, and so this function cannot be
...@@ -282,7 +283,7 @@ faulthandler_fatal_error( ...@@ -282,7 +283,7 @@ faulthandler_fatal_error(
raise(signum); raise(signum);
} }
/* Install handler for fatal signals (SIGSEGV, SIGFPE, ...). */ /* Install the handler for fatal signals, faulthandler_fatal_error(). */
static PyObject* static PyObject*
faulthandler_enable(PyObject *self, PyObject *args, PyObject *kwargs) faulthandler_enable(PyObject *self, PyObject *args, PyObject *kwargs)
...@@ -714,6 +715,20 @@ faulthandler_sigfpe(PyObject *self, PyObject *args) ...@@ -714,6 +715,20 @@ faulthandler_sigfpe(PyObject *self, PyObject *args)
Py_RETURN_NONE; 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 #ifdef SIGBUS
static PyObject * static PyObject *
faulthandler_sigbus(PyObject *self, PyObject *args) faulthandler_sigbus(PyObject *self, PyObject *args)
...@@ -847,6 +862,8 @@ static PyMethodDef module_methods[] = { ...@@ -847,6 +862,8 @@ static PyMethodDef module_methods[] = {
"a SIGSEGV or SIGBUS signal depending on the platform")}, "a SIGSEGV or SIGBUS signal depending on the platform")},
{"_sigsegv", faulthandler_sigsegv, METH_VARARGS, {"_sigsegv", faulthandler_sigsegv, METH_VARARGS,
PyDoc_STR("_sigsegv(): raise a SIGSEGV signal")}, 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, {"_sigfpe", (PyCFunction)faulthandler_sigfpe, METH_NOARGS,
PyDoc_STR("_sigfpe(): raise a SIGFPE signal")}, PyDoc_STR("_sigfpe(): raise a SIGFPE signal")},
#ifdef SIGBUS #ifdef SIGBUS
......
...@@ -2124,6 +2124,7 @@ Py_FatalError(const char *msg) ...@@ -2124,6 +2124,7 @@ Py_FatalError(const char *msg)
fflush(stderr); fflush(stderr);
_Py_DumpTraceback(fd, tstate); _Py_DumpTraceback(fd, tstate);
} }
_PyFaulthandler_Fini();
} }
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
......
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