Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d727e23

Browse files
author
Victor Stinner
committed
Issue #11393: The fault handler handles also SIGABRT
1 parent bc6a4db commit d727e23

5 files changed

Lines changed: 45 additions & 17 deletions

File tree

Doc/library/faulthandler.rst

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66

77
This module contains functions to dump the Python traceback explicitly, on a
88
fault, after a timeout or on a user signal. Call :func:`faulthandler.enable` to
9-
install fault handlers for :const:`SIGSEGV`, :const:`SIGFPE`, :const:`SIGBUS`
10-
and :const:`SIGILL` signals. You can also enable them at startup by setting the
11-
:envvar:`PYTHONFAULTHANDLER` environment variable or by using :option:`-X`
12-
``faulthandler`` command line option.
9+
install fault handlers for :const:`SIGSEGV`, :const:`SIGFPE`, :const:`SIGABRT`,
10+
:const:`SIGBUS` and :const:`SIGILL` signals. You can also enable them at
11+
startup by setting the :envvar:`PYTHONFAULTHANDLER` environment variable or by
12+
using :option:`-X` ``faulthandler`` command line option.
1313

1414
The fault handler is compatible with system fault handlers like Apport or
1515
the Windows fault handler. The module uses an alternative stack for signal
@@ -48,9 +48,9 @@ Fault handler state
4848
.. function:: enable(file=sys.stderr, all_threads=False)
4949

5050
Enable the fault handler: install handlers for :const:`SIGSEGV`,
51-
:const:`SIGFPE`, :const:`SIGBUS` and :const:`SIGILL` signals to dump the
52-
Python traceback. It dumps the traceback of the current thread, or all
53-
threads if *all_threads* is ``True``, into *file*.
51+
:const:`SIGFPE`, :const:`SIGABRT`, :const:`SIGBUS` and :const:`SIGILL`
52+
signals to dump the Python traceback. It dumps the traceback of the current
53+
thread, or all threads if *all_threads* is ``True``, into *file*.
5454

5555
.. function:: disable()
5656

Doc/using/cmdline.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -502,8 +502,9 @@ These environment variables influence Python's behavior.
502502

503503
If this environment variable is set, :func:`faulthandler.enable` is called
504504
at startup: install a handler for :const:`SIGSEGV`, :const:`SIGFPE`,
505-
:const:`SIGBUS` and :const:`SIGILL` signals to dump the Python traceback.
506-
This is equivalent to :option:`-X` ``faulthandler`` option.
505+
:const:`SIGABRT`, :const:`SIGBUS` and :const:`SIGILL` signals to dump the
506+
Python traceback. This is equivalent to :option:`-X` ``faulthandler``
507+
option.
507508

508509

509510
Debug-mode variables

Lib/test/test_faulthandler.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,15 @@ def test_sigsegv(self):
112112
3,
113113
'Segmentation fault')
114114

115+
def test_sigabrt(self):
116+
self.check_fatal_error("""
117+
import faulthandler
118+
faulthandler.enable()
119+
faulthandler._sigabrt()
120+
""".strip(),
121+
3,
122+
'Aborted')
123+
115124
@unittest.skipIf(sys.platform == 'win32',
116125
"SIGFPE cannot be caught on Windows")
117126
def test_sigfpe(self):

Modules/faulthandler.c

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
#endif
1111

1212
#ifndef MS_WINDOWS
13-
/* register() is useless on Windows, because only SIGSEGV and SIGILL can be
14-
handled by the process, and these signals can only be used with enable(),
15-
not using register() */
13+
/* register() is useless on Windows, because only SIGSEGV, SIGABRT and
14+
SIGILL can be handled by the process, and these signals can only be used
15+
with enable(), not using register() */
1616
# define FAULTHANDLER_USER
1717
#endif
1818

@@ -96,6 +96,7 @@ static fault_handler_t faulthandler_handlers[] = {
9696
{SIGILL, 0, "Illegal instruction", },
9797
#endif
9898
{SIGFPE, 0, "Floating point exception", },
99+
{SIGABRT, 0, "Aborted", },
99100
/* define SIGSEGV at the end to make it the default choice if searching the
100101
handler fails in faulthandler_fatal_error() */
101102
{SIGSEGV, 0, "Segmentation fault", }
@@ -202,7 +203,7 @@ faulthandler_dump_traceback_py(PyObject *self,
202203
}
203204

204205

205-
/* Handler of SIGSEGV, SIGFPE, SIGBUS and SIGILL signals.
206+
/* Handler of SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL signals.
206207
207208
Display the current Python traceback, restore the previous handler and call
208209
the previous handler.
@@ -253,9 +254,9 @@ faulthandler_fatal_error(
253254
PUTS(fd, handler->name);
254255
PUTS(fd, "\n\n");
255256

256-
/* SIGSEGV, SIGFPE, SIGBUS and SIGILL are synchronous signals and so are
257-
delivered to the thread that caused the fault. Get the Python thread
258-
state of the current thread.
257+
/* SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals and
258+
so are delivered to the thread that caused the fault. Get the Python
259+
thread state of the current thread.
259260
260261
PyThreadState_Get() doesn't give the state of the thread that caused the
261262
fault if the thread released the GIL, and so this function cannot be
@@ -282,7 +283,7 @@ faulthandler_fatal_error(
282283
raise(signum);
283284
}
284285

285-
/* Install handler for fatal signals (SIGSEGV, SIGFPE, ...). */
286+
/* Install the handler for fatal signals, faulthandler_fatal_error(). */
286287

287288
static PyObject*
288289
faulthandler_enable(PyObject *self, PyObject *args, PyObject *kwargs)
@@ -714,6 +715,20 @@ faulthandler_sigfpe(PyObject *self, PyObject *args)
714715
Py_RETURN_NONE;
715716
}
716717

718+
static PyObject *
719+
faulthandler_sigabrt(PyObject *self, PyObject *args)
720+
{
721+
#if _MSC_VER
722+
/* If Python is compiled in debug mode with Visual Studio, abort() opens
723+
a popup asking the user how to handle the assertion. Use raise(SIGABRT)
724+
instead. */
725+
raise(SIGABRT);
726+
#else
727+
abort();
728+
#endif
729+
Py_RETURN_NONE;
730+
}
731+
717732
#ifdef SIGBUS
718733
static PyObject *
719734
faulthandler_sigbus(PyObject *self, PyObject *args)
@@ -847,6 +862,8 @@ static PyMethodDef module_methods[] = {
847862
"a SIGSEGV or SIGBUS signal depending on the platform")},
848863
{"_sigsegv", faulthandler_sigsegv, METH_VARARGS,
849864
PyDoc_STR("_sigsegv(): raise a SIGSEGV signal")},
865+
{"_sigabrt", faulthandler_sigabrt, METH_VARARGS,
866+
PyDoc_STR("_sigabrt(): raise a SIGABRT signal")},
850867
{"_sigfpe", (PyCFunction)faulthandler_sigfpe, METH_NOARGS,
851868
PyDoc_STR("_sigfpe(): raise a SIGFPE signal")},
852869
#ifdef SIGBUS

Python/pythonrun.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2124,6 +2124,7 @@ Py_FatalError(const char *msg)
21242124
fflush(stderr);
21252125
_Py_DumpTraceback(fd, tstate);
21262126
}
2127+
_PyFaulthandler_Fini();
21272128
}
21282129

21292130
#ifdef MS_WINDOWS

0 commit comments

Comments
 (0)