[Python-checkins] cpython (merge 3.4 -> default): (Merge 3.4) Issue #23571: Enhance Py_FatalError()
victor.stinner
python-checkins at python.org
Tue Mar 24 12:10:39 CET 2015
https://hg.python.org/cpython/rev/6303795f035a
changeset: 95154:6303795f035a
parent: 95152:d6791e4026f1
parent: 95153:efb2c9ac2f88
user: Victor Stinner <victor.stinner at gmail.com>
date: Tue Mar 24 12:01:30 2015 +0100
summary:
(Merge 3.4) Issue #23571: Enhance Py_FatalError()
* Display the current Python stack if an exception was raised but the exception
has no traceback
* Disable faulthandler if an exception was raised (before it was only disabled
if no exception was raised)
* To display the current Python stack, call PyGILState_GetThisThreadState()
which works even if the GIL was released
files:
Python/pylifecycle.c | 72 ++++++++++++++++++++++++++-----
1 files changed, 59 insertions(+), 13 deletions(-)
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -1244,28 +1244,74 @@
}
+/* Print the current exception (if an exception is set) with its traceback,
+ * or display the current Python stack.
+ *
+ * Don't call PyErr_PrintEx() and the except hook, because Py_FatalError() is
+ * called on catastrophic cases. */
+
+static void
+_Py_PrintFatalError(int fd)
+{
+ PyObject *exception, *v, *tb;
+ int has_tb;
+ PyThreadState *tstate;
+
+ PyErr_Fetch(&exception, &v, &tb);
+ if (exception == NULL) {
+ /* No current exception */
+ goto display_stack;
+ }
+
+ PyErr_NormalizeException(&exception, &v, &tb);
+ if (tb == NULL) {
+ tb = Py_None;
+ Py_INCREF(tb);
+ }
+ PyException_SetTraceback(v, tb);
+ if (exception == NULL) {
+ /* too bad, PyErr_NormalizeException() failed */
+ goto display_stack;
+ }
+
+ has_tb = (tb != NULL && tb != Py_None);
+ PyErr_Display(exception, v, tb);
+ Py_XDECREF(exception);
+ Py_XDECREF(v);
+ Py_XDECREF(tb);
+ if (has_tb)
+ return;
+
+display_stack:
+ /* PyGILState_GetThisThreadState() works even if the GIL was released */
+ tstate = PyGILState_GetThisThreadState();
+ if (tstate == NULL) {
+ /* _Py_DumpTracebackThreads() requires the thread state to display
+ * frames */
+ return;
+ }
+
+ fputc('\n', stderr);
+ fflush(stderr);
+
+ /* display the current Python stack */
+ _Py_DumpTracebackThreads(fd, tstate->interp, tstate);
+}
/* Print fatal error message and abort */
void
Py_FatalError(const char *msg)
{
const int fd = fileno(stderr);
- PyThreadState *tstate;
fprintf(stderr, "Fatal Python error: %s\n", msg);
fflush(stderr); /* it helps in Windows debug build */
- if (PyErr_Occurred()) {
- PyErr_PrintEx(0);
- }
- else {
- tstate = (PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current);
- if (tstate != NULL) {
- fputc('\n', stderr);
- fflush(stderr);
- _Py_DumpTracebackThreads(fd, tstate->interp, tstate);
- }
- _PyFaulthandler_Fini();
- }
+
+ _Py_PrintFatalError(fd);
+
+ /* The main purpose of faulthandler is to display the traceback. We already
+ * did our best to display it. So faulthandler can now be disabled. */
+ _PyFaulthandler_Fini();
#ifdef MS_WINDOWS
{
--
Repository URL: https://hg.python.org/cpython
More information about the Python-checkins
mailing list