From be0c19291c0d52a031f0d6eaaeda44fdb3db939e Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Mon, 28 Jul 2025 20:38:12 +0000 Subject: [PATCH 1/2] gh-137185: Fix `_Py_DumpStack()` async signal safety Call backtrace() once when installing the signal handler to ensure that libgcc is dynamically loaded outside the signal handler. This fixes a "signal-unsafe call inside of a signal" TSan error from test_faulthandler.test_enable_fd. --- Include/internal/pycore_traceback.h | 1 + .../2025-07-28-20-48-32.gh-issue-137185.fgI7-B.rst | 2 ++ Modules/faulthandler.c | 5 +++++ Python/traceback.c | 10 ++++++++++ 4 files changed, 18 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2025-07-28-20-48-32.gh-issue-137185.fgI7-B.rst diff --git a/Include/internal/pycore_traceback.h b/Include/internal/pycore_traceback.h index d71dd2886999a6..a4f125e073d3d1 100644 --- a/Include/internal/pycore_traceback.h +++ b/Include/internal/pycore_traceback.h @@ -100,6 +100,7 @@ extern int _Py_WriteIndentedMargin(int, const char*, PyObject *); extern int _Py_WriteIndent(int, PyObject *); // Export for the faulthandler module +PyAPI_FUNC(void) _Py_InitDumpStack(void); PyAPI_FUNC(void) _Py_DumpStack(int fd); #ifdef __cplusplus diff --git a/Misc/NEWS.d/next/Library/2025-07-28-20-48-32.gh-issue-137185.fgI7-B.rst b/Misc/NEWS.d/next/Library/2025-07-28-20-48-32.gh-issue-137185.fgI7-B.rst new file mode 100644 index 00000000000000..89398dff147394 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-07-28-20-48-32.gh-issue-137185.fgI7-B.rst @@ -0,0 +1,2 @@ +Fix a potential async-signal-safety issue in :mod:`faulthandler` when +printing C stack traces. diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index 73bea8172c7253..84cfc6bd8ef6e4 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -524,6 +524,11 @@ faulthandler_enable(void) } #endif + // gh-137185: Initialize C stack trace dumping outside of the signal + // handler. Specifically, we call backtrace() to ensure that libgcc is + // dynamically loaded outside of the signal handler. + _Py_InitDumpStack(); + for (size_t i=0; i < faulthandler_nsignals; i++) { fault_handler_t *handler; int err; diff --git a/Python/traceback.c b/Python/traceback.c index 4f674eaf55715b..a3ac7985f66fa0 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -1326,3 +1326,13 @@ _Py_DumpStack(int fd) PUTS(fd, " \n"); } #endif + +void +_Py_InitDumpStack(void) +{ +#ifdef CAN_C_BACKTRACE + // gh-137185: Call backtrace() once to force libgcc to be loaded early. + void *callstack[1]; + backtrace(callstack, 1); +#endif +} From 0dc1cc2ff5a30170b8c2f89142b95e2c8439dcc6 Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Tue, 29 Jul 2025 13:59:50 +0000 Subject: [PATCH 2/2] (void)backtrace(...) --- Python/traceback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/traceback.c b/Python/traceback.c index a3ac7985f66fa0..da7956d1ec47b4 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -1333,6 +1333,6 @@ _Py_InitDumpStack(void) #ifdef CAN_C_BACKTRACE // gh-137185: Call backtrace() once to force libgcc to be loaded early. void *callstack[1]; - backtrace(callstack, 1); + (void)backtrace(callstack, 1); #endif }