Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Include/internal/pycore_traceback.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,16 @@ extern void _Py_DumpTraceback(
It is better to pass NULL to interp and current_tstate, the function tries
different options to retrieve this information.

If skip_current_tstate is 1 then first tstate (current_tstate) will be skiped.
Comment thread
sergey-miryanov marked this conversation as resolved.
Resolved
This flag used in faulthandler_thread to skip self.

This function is signal safe. */

extern const char* _Py_DumpTracebackThreads(
int fd,
PyInterpreterState *interp,
PyThreadState *current_tstate);
PyThreadState *current_tstate,
int skip_current_tstate);

/* Write a Unicode object into the file descriptor fd. Encode the string to
ASCII using the backslashreplace error handler.
Expand Down
35 changes: 30 additions & 5 deletions Modules/faulthandler.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ faulthandler_dump_traceback(int fd, int all_threads,
PyThreadState *tstate = PyGILState_GetThisThreadState();

if (all_threads == 1) {
(void)_Py_DumpTracebackThreads(fd, NULL, tstate);
(void)_Py_DumpTracebackThreads(fd, NULL, tstate, 0);
}
else {
if (all_threads == FT_IGNORE_ALL_THREADS) {
Expand Down Expand Up @@ -273,7 +273,7 @@ faulthandler_dump_traceback_py_impl(PyObject *module, PyObject *file,
/* gh-128400: Accessing other thread states while they're running
* isn't safe if those threads are running. */
_PyEval_StopTheWorld(interp);
errmsg = _Py_DumpTracebackThreads(fd, NULL, tstate);
errmsg = _Py_DumpTracebackThreads(fd, NULL, tstate, 0);
_PyEval_StartTheWorld(interp);
if (errmsg != NULL) {
PyErr_SetString(PyExc_RuntimeError, errmsg);
Expand Down Expand Up @@ -677,12 +677,19 @@ faulthandler_is_enabled_impl(PyObject *module)
return fatal_error.enabled;
}

// TODO: remove
static int
interp_is_freed(PyInterpreterState *interp)
{
return _PyMem_IsPtrFreed(interp);
}

static void
faulthandler_thread(void *unused)
{
PyLockStatus st;
const char* errmsg;
int ok;
int ok = 1;
#if defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK)
sigset_t set;

Expand All @@ -703,8 +710,26 @@ faulthandler_thread(void *unused)

(void)_Py_write_noraise(thread.fd, thread.header, (int)thread.header_len);

errmsg = _Py_DumpTracebackThreads(thread.fd, thread.interp, NULL);
ok = (errmsg == NULL);
PyInterpreterState *interp = thread.interp;
assert(interp != NULL);

if (!interp_is_freed(interp)) {

#ifdef Py_GIL_DISABLED
_PyEval_StopTheWorld(interp);
#else
PyGILState_STATE gil_state = PyGILState_Ensure();
Comment thread
sergey-miryanov marked this conversation as resolved.
Resolved
#endif
errmsg = _Py_DumpTracebackThreads(thread.fd, interp, NULL, 1);
ok = (errmsg == NULL);

#ifdef Py_GIL_DISABLED
_PyEval_StartTheWorld(interp);
#else
PyGILState_Release(gil_state);
#endif
}


if (thread.exit)
_exit(1);
Expand Down
2 changes: 1 addition & 1 deletion Python/pylifecycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -3139,7 +3139,7 @@ _Py_FatalError_DumpTracebacks(int fd, PyInterpreterState *interp,

/* display the current Python stack */
#ifndef Py_GIL_DISABLED
_Py_DumpTracebackThreads(fd, interp, tstate);
_Py_DumpTracebackThreads(fd, interp, tstate, 0);
#else
_Py_DumpTraceback(fd, tstate);
#endif
Expand Down
9 changes: 8 additions & 1 deletion Python/traceback.c
Original file line number Diff line number Diff line change
Expand Up @@ -1239,7 +1239,8 @@ write_thread_id(int fd, PyThreadState *tstate, int is_current)
handlers if signals were received. */
const char*
_Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
PyThreadState *current_tstate)
PyThreadState *current_tstate,
int skip_current_tstate)
{
if (current_tstate == NULL) {
/* _Py_DumpTracebackThreads() is called from signal handlers by
Expand Down Expand Up @@ -1289,6 +1290,12 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
_Py_BEGIN_SUPPRESS_IPH
do
{
if (skip_current_tstate && current_tstate == tstate) {
tstate = PyThreadState_Next(tstate);
skip_current_tstate = 0;
continue;
}

if (nthreads != 0)
PUTS(fd, "\n");
if (nthreads >= MAX_NTHREADS) {
Expand Down
Loading