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

Skip to content

Commit 0e98a76

Browse files
committed
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
1 parent 2e3998f commit 0e98a76

1 file changed

Lines changed: 60 additions & 13 deletions

File tree

Python/pythonrun.c

Lines changed: 60 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2587,28 +2587,75 @@ err_input(perrdetail *err)
25872587
}
25882588
}
25892589

2590+
/* Print the current exception (if an exception is set) with its traceback,
2591+
* or display the current Python stack.
2592+
*
2593+
* Don't call PyErr_PrintEx() and the except hook, because Py_FatalError() is
2594+
* called on catastrophic cases. */
2595+
2596+
static void
2597+
_Py_PrintFatalError(int fd)
2598+
{
2599+
PyObject *exception, *v, *tb;
2600+
int has_tb;
2601+
PyThreadState *tstate;
2602+
2603+
PyErr_Fetch(&exception, &v, &tb);
2604+
if (exception == NULL) {
2605+
/* No current exception */
2606+
goto display_stack;
2607+
}
2608+
2609+
PyErr_NormalizeException(&exception, &v, &tb);
2610+
if (tb == NULL) {
2611+
tb = Py_None;
2612+
Py_INCREF(tb);
2613+
}
2614+
PyException_SetTraceback(v, tb);
2615+
if (exception == NULL) {
2616+
/* too bad, PyErr_NormalizeException() failed */
2617+
goto display_stack;
2618+
}
2619+
2620+
has_tb = (tb != NULL && tb != Py_None);
2621+
PyErr_Display(exception, v, tb);
2622+
Py_XDECREF(exception);
2623+
Py_XDECREF(v);
2624+
Py_XDECREF(tb);
2625+
if (has_tb)
2626+
return;
2627+
2628+
display_stack:
2629+
/* PyGILState_GetThisThreadState() works even if the GIL was released */
2630+
tstate = PyGILState_GetThisThreadState();
2631+
if (tstate == NULL) {
2632+
/* _Py_DumpTracebackThreads() requires the thread state to display
2633+
* frames */
2634+
return;
2635+
}
2636+
2637+
fputc('\n', stderr);
2638+
fflush(stderr);
2639+
2640+
/* display the current Python stack */
2641+
_Py_DumpTracebackThreads(fd, tstate->interp, tstate);
2642+
}
2643+
25902644
/* Print fatal error message and abort */
25912645

25922646
void
25932647
Py_FatalError(const char *msg)
25942648
{
25952649
const int fd = fileno(stderr);
2596-
PyThreadState *tstate;
25972650

25982651
fprintf(stderr, "Fatal Python error: %s\n", msg);
25992652
fflush(stderr); /* it helps in Windows debug build */
2600-
if (PyErr_Occurred()) {
2601-
PyErr_PrintEx(0);
2602-
}
2603-
else {
2604-
tstate = _Py_atomic_load_relaxed(&_PyThreadState_Current);
2605-
if (tstate != NULL) {
2606-
fputc('\n', stderr);
2607-
fflush(stderr);
2608-
_Py_DumpTracebackThreads(fd, tstate->interp, tstate);
2609-
}
2610-
_PyFaulthandler_Fini();
2611-
}
2653+
2654+
_Py_PrintFatalError(fd);
2655+
2656+
/* The main purpose of faulthandler is to display the traceback. We already
2657+
* did our best to display it. So faulthandler can now be disabled. */
2658+
_PyFaulthandler_Fini();
26122659

26132660
#ifdef MS_WINDOWS
26142661
{

0 commit comments

Comments
 (0)