Raise an error if the output doesn't match the expected format.
"""
- if all_threads:
+ all_threads_disabled = (
+ (not py_fatal_error)
+ and all_threads
+ and (not sys._is_gil_enabled())
+ )
+ if all_threads and not all_threads_disabled:
if know_current_thread:
header = 'Current thread 0x[0-9a-f]+'
else:
if py_fatal_error:
regex.append("Python runtime state: initialized")
regex.append('')
+ if all_threads_disabled:
+ regex.append("<Cannot show all threads while the GIL is disabled>")
regex.append(fr'{header} \(most recent call first\):')
- if garbage_collecting:
+ if garbage_collecting and not all_threads_disabled:
regex.append(' Garbage-collecting')
regex.append(fr' File "<string>", line {lineno} in {function}')
regex = '\n'.join(regex)
#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()
# 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)
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);
}
#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) {
+ return 0;
+ }
+
+ /* 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.
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);
}
}
- faulthandler_dump_traceback(fd, fatal_error.all_threads,
+ faulthandler_dump_traceback(fd, deduce_all_threads(),
fatal_error.interp);
/* call the next exception handler */