From 7ed2b6b5876f82d4658eb7601c32b0910b5926b6 Mon Sep 17 00:00:00 2001 From: Sergey Miryanov Date: Sat, 8 Nov 2025 16:02:43 +0500 Subject: [PATCH 1/2] Acquire tstate and stop the world in faulthandler_user --- Include/internal/pycore_faulthandler.h | 1 + Modules/faulthandler.c | 28 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/Include/internal/pycore_faulthandler.h b/Include/internal/pycore_faulthandler.h index 78cd657e6ae5ae..c968a1a2a0e58b 100644 --- a/Include/internal/pycore_faulthandler.h +++ b/Include/internal/pycore_faulthandler.h @@ -42,6 +42,7 @@ struct faulthandler_user_signal { int chain; _Py_sighandler_t previous; PyInterpreterState *interp; + PyThreadState *tstate; }; #endif /* FAULTHANDLER_USER */ diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index 9b8c77e2b0401f..04ad4f5198369a 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -945,8 +945,26 @@ faulthandler_user(int signum) if (!user->enabled) return; + PyThreadState *tstate = PyGILState_GetThisThreadState(); + if (!tstate) { + tstate = user->tstate; + } + + if (tstate) { + assert (user->interp); + + _PyThreadState_Attach(tstate); + _PyEval_StopTheWorld(user->interp); + } + faulthandler_dump_traceback(user->fd, user->all_threads, user->interp); + if (tstate) { + assert (user->interp); + _PyEval_StartTheWorld(user->interp); + _PyThreadState_Detach(tstate); + } + #ifdef HAVE_SIGACTION if (user->chain) { (void)sigaction(signum, &user->previous, NULL); @@ -1056,8 +1074,14 @@ faulthandler_register_py_impl(PyObject *module, int signum, PyObject *file, user->all_threads = all_threads; user->chain = chain; user->interp = PyThreadState_GetInterpreter(tstate); + user->tstate = PyThreadState_New(user->interp); user->enabled = 1; + if (!user->tstate) { + Py_XDECREF(file); + return NULL; + } + Py_RETURN_NONE; } @@ -1073,6 +1097,10 @@ faulthandler_unregister(user_signal_t *user, int signum) (void)signal(signum, user->previous); #endif Py_CLEAR(user->file); + if (user->tstate) { + PyThreadState_Clear(user->tstate); + user->tstate = NULL; + } user->fd = -1; return 1; } From c8e89f0659642e1b96098212a7d6b90c4d5ddf11 Mon Sep 17 00:00:00 2001 From: Sergey Miryanov Date: Sat, 8 Nov 2025 23:26:48 +0500 Subject: [PATCH 2/2] Fix --- Include/internal/pycore_faulthandler.h | 1 - Modules/faulthandler.c | 33 ++++++++++++-------------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/Include/internal/pycore_faulthandler.h b/Include/internal/pycore_faulthandler.h index c968a1a2a0e58b..78cd657e6ae5ae 100644 --- a/Include/internal/pycore_faulthandler.h +++ b/Include/internal/pycore_faulthandler.h @@ -42,7 +42,6 @@ struct faulthandler_user_signal { int chain; _Py_sighandler_t previous; PyInterpreterState *interp; - PyThreadState *tstate; }; #endif /* FAULTHANDLER_USER */ diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index 04ad4f5198369a..93ae9b16766df5 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -945,23 +945,30 @@ faulthandler_user(int signum) if (!user->enabled) return; - PyThreadState *tstate = PyGILState_GetThisThreadState(); + int attach = 0; + PyThreadState *tstate = PyThreadState_GetUnchecked(); if (!tstate) { - tstate = user->tstate; + tstate = PyGILState_GetThisThreadState(); + if (tstate) { + attach = 1; + } } - if (tstate) { - assert (user->interp); - + if (attach) { _PyThreadState_Attach(tstate); - _PyEval_StopTheWorld(user->interp); } + if (user->all_threads) { + assert (user->interp); + _PyEval_StopTheWorld(user->interp); + } faulthandler_dump_traceback(user->fd, user->all_threads, user->interp); - - if (tstate) { + if (user->all_threads) { assert (user->interp); _PyEval_StartTheWorld(user->interp); + } + + if (attach) { _PyThreadState_Detach(tstate); } @@ -1074,14 +1081,8 @@ faulthandler_register_py_impl(PyObject *module, int signum, PyObject *file, user->all_threads = all_threads; user->chain = chain; user->interp = PyThreadState_GetInterpreter(tstate); - user->tstate = PyThreadState_New(user->interp); user->enabled = 1; - if (!user->tstate) { - Py_XDECREF(file); - return NULL; - } - Py_RETURN_NONE; } @@ -1097,10 +1098,6 @@ faulthandler_unregister(user_signal_t *user, int signum) (void)signal(signum, user->previous); #endif Py_CLEAR(user->file); - if (user->tstate) { - PyThreadState_Clear(user->tstate); - user->tstate = NULL; - } user->fd = -1; return 1; }