Skip to content

Commit 11a8652

Browse files
authored
gh-137185: Fix _Py_DumpStack() async signal safety (gh-137187)
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.
1 parent d7e12a3 commit 11a8652

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
@@ -524,6 +524,11 @@ faulthandler_enable(void)
524524
}
525525
#endif
526526

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

Python/traceback.c

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

0 commit comments

Comments
 (0)