-
-
Notifications
You must be signed in to change notification settings - Fork 33.1k
gh-128400: Only show the current thread in faulthandler
if the GIL is disabled
#128425
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
95424ce
8d35bb6
aadadde
170aa2a
ed23233
5622f42
6089577
b710acb
b1677f3
11bb638
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Only show the current thread in :mod:`faulthandler` on the :term:`free | ||
threaded <free threading>` build to prevent races. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
#include "Python.h" | ||
#include "pycore_ceval.h" // _PyEval_IsGILEnabled | ||
#include "pycore_initconfig.h" // _PyStatus_ERR | ||
#include "pycore_pyerrors.h" // _Py_DumpExtensionModules | ||
#include "pycore_pystate.h" // _PyThreadState_GET() | ||
|
@@ -27,6 +28,8 @@ | |
# include <sys/auxv.h> // getauxval() | ||
#endif | ||
|
||
/* Sentinel to ignore all_threads on free-threading */ | ||
#define FT_IGNORE_ALL_THREADS 2 | ||
|
||
/* Allocate at maximum 100 MiB of the stack to raise the stack overflow */ | ||
#define STACK_OVERFLOW_MAX_SIZE (100 * 1024 * 1024) | ||
|
@@ -201,10 +204,14 @@ faulthandler_dump_traceback(int fd, int all_threads, | |
PyGILState_GetThisThreadState(). */ | ||
PyThreadState *tstate = PyGILState_GetThisThreadState(); | ||
|
||
if (all_threads) { | ||
if (all_threads == 1) { | ||
(void)_Py_DumpTracebackThreads(fd, NULL, tstate); | ||
} | ||
else { | ||
if (all_threads == FT_IGNORE_ALL_THREADS) | ||
{ | ||
PUTS(fd, "<Cannot show all threads while the GIL is disabled>\n"); | ||
} | ||
if (tstate != NULL) | ||
_Py_DumpTraceback(fd, tstate); | ||
} | ||
|
@@ -266,6 +273,33 @@ faulthandler_disable_fatal_handler(fault_handler_t *handler) | |
#endif | ||
} | ||
|
||
static int | ||
deduce_all_threads(void) | ||
{ | ||
#ifndef Py_GIL_DISABLED | ||
return fatal_error.all_threads; | ||
#else | ||
if (fatal_error.all_threads == 0) { | ||
return 0; | ||
} | ||
// We can't use _PyThreadState_GET, so use the stored GILstate one | ||
PyThreadState *tstate = PyGILState_GetThisThreadState(); | ||
if (tstate == NULL) | ||
{ | ||
ZeroIntensity marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
return 0; | ||
} | ||
if (tstate->interp->gc.collecting) | ||
|
||
{ | ||
// Yay! All threads are paused, it's safe to access them. | ||
return 1; | ||
} | ||
|
||
/* In theory, it's safe to dump all threads if the GIL is enabled */ | ||
return _PyEval_IsGILEnabled(tstate) | ||
? fatal_error.all_threads | ||
: FT_IGNORE_ALL_THREADS; | ||
#endif | ||
} | ||
|
||
/* Handler for SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL signals. | ||
|
||
|
@@ -320,7 +354,7 @@ faulthandler_fatal_error(int signum) | |
PUTS(fd, "\n\n"); | ||
} | ||
|
||
faulthandler_dump_traceback(fd, fatal_error.all_threads, | ||
faulthandler_dump_traceback(fd, deduce_all_threads(), | ||
fatal_error.interp); | ||
|
||
_Py_DumpExtensionModules(fd, fatal_error.interp); | ||
|
@@ -396,7 +430,7 @@ faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info) | |
} | ||
} | ||
|
||
faulthandler_dump_traceback(fd, fatal_error.all_threads, | ||
faulthandler_dump_traceback(fd, deduce_all_threads(), | ||
fatal_error.interp); | ||
|
||
/* call the next exception handler */ | ||
|
Uh oh!
There was an error while loading. Please reload this page.