Skip to content

Commit 0f670f0

Browse files
committed
Move the function that calls backtrace() to within the core.
1 parent 8198997 commit 0f670f0

3 files changed

Lines changed: 65 additions & 65 deletions

File tree

Include/internal/pycore_traceback.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ extern int _PyTraceBack_Print(
100100
extern int _Py_WriteIndentedMargin(int, const char*, PyObject *);
101101
extern int _Py_WriteIndent(int, PyObject *);
102102

103+
// Export for the faulthandler module
104+
PyAPI_FUNC(void)
105+
_Py_DumpStack(int fd);
106+
103107
#ifdef __cplusplus
104108
}
105109
#endif

Modules/faulthandler.c

Lines changed: 2 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@
1010
#ifdef HAVE_UNISTD_H
1111
# include <unistd.h> // _exit()
1212
#endif
13-
#ifdef HAVE_EXECINFO_H
14-
# include <execinfo.h> // backtrace(), backtrace_symbols()
15-
#endif
1613

1714
#include <signal.h> // sigaction()
1815
#include <stdlib.h> // abort()
@@ -216,66 +213,6 @@ faulthandler_dump_traceback(int fd, int all_threads,
216213
reentrant = 0;
217214
}
218215

219-
#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && defined(HAVE_BACKTRACE_SYMBOLS)
220-
static void
221-
faulthandler_stack_dump_impl(int fd)
222-
{
223-
#define BACKTRACE_SIZE 32
224-
#define TRACEBACK_ENTRY_MAX_SIZE 256
225-
void *callstack[BACKTRACE_SIZE];
226-
int frames = backtrace(callstack, BACKTRACE_SIZE);
227-
if (frames == 0) {
228-
// Some systems won't return anything for the stack trace
229-
PUTS(fd, " <system returned no stack trace>\n");
230-
return;
231-
}
232-
233-
char **strings = backtrace_symbols(callstack, BACKTRACE_SIZE);
234-
if (strings == NULL) {
235-
PUTS(fd, " <not enough memory to get stack trace>\n");
236-
return;
237-
}
238-
for (int i = 0; i < frames; ++i) {
239-
char entry_str[TRACEBACK_ENTRY_MAX_SIZE];
240-
snprintf(entry_str, TRACEBACK_ENTRY_MAX_SIZE, " %s\n", strings[i]);
241-
size_t length = strlen(entry_str) + 1;
242-
if (length == TRACEBACK_ENTRY_MAX_SIZE) {
243-
/* We exceeded the size, make it look prettier */
244-
// Add ellipsis to last 3 characters
245-
entry_str[TRACEBACK_ENTRY_MAX_SIZE - 5] = '.';
246-
entry_str[TRACEBACK_ENTRY_MAX_SIZE - 4] = '.';
247-
entry_str[TRACEBACK_ENTRY_MAX_SIZE - 3] = '.';
248-
// Ensure trailing newline
249-
entry_str[TRACEBACK_ENTRY_MAX_SIZE - 2] = '\n';
250-
// Ensure that it's null-terminated
251-
entry_str[TRACEBACK_ENTRY_MAX_SIZE - 1] = '\0';
252-
}
253-
_Py_write_noraise(fd, entry_str, length);
254-
}
255-
256-
if (frames == BACKTRACE_SIZE) {
257-
PUTS(fd, " <truncated rest of calls>\n");
258-
}
259-
260-
free(strings);
261-
#undef BACKTRACE_SIZE
262-
#undef TRACEBACK_ENTRY_MAX_SIZE
263-
}
264-
#else
265-
static void
266-
faulthandler_stack_dump_impl(int fd)
267-
{
268-
PUTS(fd, " <cannot get C stack on this system>\n");
269-
}
270-
#endif
271-
272-
static void
273-
faulthandler_dump_c_stack_nocheck(int fd)
274-
{
275-
PUTS(fd, "Current thread's C stack trace (most recent call first):\n");
276-
faulthandler_stack_dump_impl(fd);
277-
}
278-
279216
static void
280217
faulthandler_dump_c_stack(int fd)
281218
{
@@ -288,7 +225,7 @@ faulthandler_dump_c_stack(int fd)
288225

289226
if (fatal_error.c_stack) {
290227
PUTS(fd, "\n");
291-
faulthandler_dump_c_stack_nocheck(fd);
228+
_Py_DumpStack(fd);
292229
}
293230

294231
reentrant = 0;
@@ -352,7 +289,7 @@ faulthandler_dump_c_stack_py(PyObject *self,
352289
return NULL;
353290
}
354291

355-
faulthandler_dump_c_stack_nocheck(fd);
292+
_Py_DumpStack(fd);
356293

357294
if (PyErr_CheckSignals()) {
358295
return NULL;

Python/traceback.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
#ifdef HAVE_UNISTD_H
2222
# include <unistd.h> // lseek()
2323
#endif
24+
#ifdef HAVE_EXECINFO_H
25+
# include <execinfo.h> // backtrace(), backtrace_symbols()
26+
#endif
2427

2528

2629
#define OFF(x) offsetof(PyTracebackObject, x)
@@ -1101,3 +1104,59 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
11011104
return NULL;
11021105
}
11031106

1107+
/* This is for faulthandler.
1108+
* Apparently, backtrace() doesn't play well across DLL boundaries on macOS */
1109+
#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && defined(HAVE_BACKTRACE_SYMBOLS)
1110+
void
1111+
_Py_DumpStack(int fd)
1112+
{
1113+
#define BACKTRACE_SIZE 32
1114+
#define TRACEBACK_ENTRY_MAX_SIZE 256
1115+
PUTS(fd, "Current thread's C stack trace (most recent call first):\n");
1116+
void *callstack[BACKTRACE_SIZE];
1117+
int frames = backtrace(callstack, BACKTRACE_SIZE);
1118+
if (frames == 0) {
1119+
// Some systems won't return anything for the stack trace
1120+
PUTS(fd, " <system returned no stack trace>\n");
1121+
return;
1122+
}
1123+
1124+
char **strings = backtrace_symbols(callstack, BACKTRACE_SIZE);
1125+
if (strings == NULL) {
1126+
PUTS(fd, " <not enough memory to get stack trace>\n");
1127+
return;
1128+
}
1129+
for (int i = 0; i < frames; ++i) {
1130+
char entry_str[TRACEBACK_ENTRY_MAX_SIZE];
1131+
snprintf(entry_str, TRACEBACK_ENTRY_MAX_SIZE, " %s\n", strings[i]);
1132+
size_t length = strlen(entry_str) + 1;
1133+
if (length == TRACEBACK_ENTRY_MAX_SIZE) {
1134+
/* We exceeded the size, make it look prettier */
1135+
// Add ellipsis to last 3 characters
1136+
entry_str[TRACEBACK_ENTRY_MAX_SIZE - 5] = '.';
1137+
entry_str[TRACEBACK_ENTRY_MAX_SIZE - 4] = '.';
1138+
entry_str[TRACEBACK_ENTRY_MAX_SIZE - 3] = '.';
1139+
// Ensure trailing newline
1140+
entry_str[TRACEBACK_ENTRY_MAX_SIZE - 2] = '\n';
1141+
// Ensure that it's null-terminated
1142+
entry_str[TRACEBACK_ENTRY_MAX_SIZE - 1] = '\0';
1143+
}
1144+
_Py_write_noraise(fd, entry_str, length);
1145+
}
1146+
1147+
if (frames == BACKTRACE_SIZE) {
1148+
PUTS(fd, " <truncated rest of calls>\n");
1149+
}
1150+
1151+
free(strings);
1152+
#undef BACKTRACE_SIZE
1153+
#undef TRACEBACK_ENTRY_MAX_SIZE
1154+
}
1155+
#else
1156+
void
1157+
_Py_DumpStack(int fd)
1158+
{
1159+
PUTS(fd, "Current thread's C stack trace (most recent call first):\n");
1160+
PUTS(fd, " <cannot get C stack on this system>\n");
1161+
}
1162+
#endif

0 commit comments

Comments
 (0)