mirror of
https://github.com/python/cpython.git
synced 2025-07-09 20:35:26 +00:00
Issue #11393: The fault handler handles also SIGABRT
This commit is contained in:
parent
bc6a4db66d
commit
d727e23243
5 changed files with 45 additions and 17 deletions
|
@ -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
|
||||||
.. 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.
|
||||||
|
|
||||||
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()
|
||||||
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 @@
|
||||||
#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[] = {
|
||||||
{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,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* 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(
|
||||||
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(
|
||||||
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)
|
||||||
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[] = {
|
||||||
"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)
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
_Py_DumpTraceback(fd, tstate);
|
_Py_DumpTraceback(fd, tstate);
|
||||||
}
|
}
|
||||||
|
_PyFaulthandler_Fini();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue