Skip to content

Commit 75de39b

Browse files
[3.14] gh-137185: Fix _Py_DumpStack() async signal safety (gh-137187) (gh-137206)
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. (cherry picked from commit 11a8652) Co-authored-by: Sam Gross <[email protected]>
1 parent 93ac6f3 commit 75de39b

File tree

4 files changed

+18
-0
lines changed

4 files changed

+18
-0
lines changed

Include/internal/pycore_traceback.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ extern int _Py_WriteIndentedMargin(int, const char*, PyObject *);
100100
extern int _Py_WriteIndent(int, PyObject *);
101101

102102
// Export for the faulthandler module
103+
PyAPI_FUNC(void) _Py_InitDumpStack(void);
103104
PyAPI_FUNC(void) _Py_DumpStack(int fd);
104105

105106
#ifdef __cplusplus
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a potential async-signal-safety issue in :mod:`faulthandler` when
2+
printing C stack traces.

Modules/faulthandler.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,11 @@ faulthandler_enable(void)
525525
}
526526
#endif
527527

528+
// gh-137185: Initialize C stack trace dumping outside of the signal
529+
// handler. Specifically, we call backtrace() to ensure that libgcc is
530+
// dynamically loaded outside of the signal handler.
531+
_Py_InitDumpStack();
532+
528533
for (size_t i=0; i < faulthandler_nsignals; i++) {
529534
fault_handler_t *handler;
530535
int err;

Python/traceback.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,3 +1327,13 @@ _Py_DumpStack(int fd)
13271327
PUTS(fd, " <cannot get C stack on this system>\n");
13281328
}
13291329
#endif
1330+
1331+
void
1332+
_Py_InitDumpStack(void)
1333+
{
1334+
#ifdef CAN_C_BACKTRACE
1335+
// gh-137185: Call backtrace() once to force libgcc to be loaded early.
1336+
void *callstack[1];
1337+
(void)backtrace(callstack, 1);
1338+
#endif
1339+
}

0 commit comments

Comments
 (0)