10000 DEBUG: add backtrace support using libbacktrace · petergeoghegan/postgres@34b8197 · GitHub
[go: up one dir, main page]

Skip to content

Commit 34b8197

Browse files
DEBUG: add backtrace support using libbacktrace
Taken from Andres' aio branch.
1 parent 41599a7 commit 34b8197

File tree

4 files changed

+129
-4
lines changed

4 files changed

+129
-4
lines changed

.cirrus.tasks.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,9 @@ task:
189189
sysctl kern.corefile='/tmp/cores/%N.%P.core'
190190
setup_additional_packages_script: |
191191
#pkg install -y ...
192+
pkg install -y curl
193+
pkg upgrade -y libssh2 # XXX shouldn't be necessary. revisit w/ FreeBSD 14
194+
pkg install -y libbacktrace
192195
193196
# NB: Intentionally build without -Dllvm. The freebsd image size is already
194197
# large enough to make VM startup slow, and even without llvm freebsd

meson.build

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2859,10 +2859,17 @@ else
28592859
socket_dep = not_found_dep
28602860
endif
28612861

2862+
backtrace_dep = cc.find_library('backtrace',
2863+
has_headers: 'backtrace.h',
2864+
header_include_directories: postgres_inc,
2865+
dirs: test_lib_d,
2866+
required: false)
2867+
28622868
# XXX: Might be worth conditioning some checks on the OS, to avoid doing
28632869
# unnecessary checks over and over, particularly on windows.
28642870
func_checks = [
28652871
['backtrace_symbols', {'dependencies': [execinfo_dep]}],
2872+
['backtrace_create_state', {'dependencies': [backtrace_dep]}],
28662873
['clock_gettime', {'dependencies': [rt_dep], 'define': false}],
28672874
['copyfile'],
28682875
['copy_file_range'],

src/backend/utils/error/assert.c

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,49 @@
1515
#include "postgres.h"
1616

1717
#include <unistd.h>
18-
#ifdef HAVE_EXECINFO_H
18+
#if defined(HAVE_BACKTRACE_CREATE_STATE)
19+
#include <backtrace.h>
20+
#elif defined(HAVE_EXECINFO_H)
1921
#include <execinfo.h>
2022
#endif
2123

24+
#ifdef HAVE_BACKTRACE_CREATE_STATE
25+
static void
26+
pg_backtrace_error_callback(void *data, const char *msg, int errnum)
27+
{
28+
char *errtrace = (char *) data;
29+
char buffer[1000];
30+
31+
memset(buffer, 0, sizeof(buffer));
32+
snprintf(buffer, sizeof(buffer), "backtrace failure: msg: %s, errnum: %d\n",
33+
msg, errnum);
34+
35+
strcat(errtrace, buffer);
36+
}
37+
38+
static int
39+
pg_backtrace_full_callback(void *data, uintptr_t pc,
40+
const char *filename, int lineno,
41+
const char *function)
42+
{
43+
char *errtrace = (char *) data;
44+
char buffer[1000];
45+
46+
if (pc == 0xffffffffffffffff)
47+
return 1;
48+
49+
memset(buffer, 0, sizeof(buffer));
50+
snprintf(buffer, sizeof(buffer), "[%p] %s: %s:%d\n",
51+
(void *) pc,
52+
function ? function : "[unknown]",
53+
filename ? filename : "[unknown]", lineno);
54+
55+
strcat(errtrace, buffer);
56+
57+
return 0;
58+
}
59+
#endif
60+
2261
/*
2362
* ExceptionalCondition - Handles the failure of an Assert()
2463
*
@@ -44,7 +83,30 @@ ExceptionalCondition(const char *conditionName,
4483
fflush(stderr);
4584

4685
/* If we have support for it, dump a simple backtrace */
47-
#ifdef HAVE_BACKTRACE_SYMBOLS
86+
#ifdef HAVE_BACKTRACE_CREATE_STATE
87+
{
88+
char buf[5000];
89+
static struct backtrace_state *state;
90+
91+
memset(buf, 0, sizeof(buf));
92+
buf[0] = '\0';
93+
state = backtrace_create_state(
94+
NULL, /* threaded = */ false,
95+
pg_backtrace_error_callback, buf);
96+
97+
/*
98+
* The state is long-lived and can't be freed. The error callback, if
99+
* necessary, will be called while backtrace_create_state() is
100+
* running, so it's ok to pass errtrace here.
101+
*/
102+
backtrace_full(state, 1,
103+
pg_backtrace_full_callback,
104+
pg_backtrace_error_callback,
105+
buf);
106+
write_stderr("%s\n", buf);
107+
fflush(stderr);
108+
}
109+
#elif defined(HAVE_BACKTRACE_SYMBOLS)
48110
{
49111
void *buf[100];
50112
int nframes;

src/backend/utils/error/elog.c

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@
6262
#ifdef HAVE_SYSLOG
6363
#include <syslog.h>
6464
#endif
65-
#ifdef HAVE_EXECINFO_H
65+
#if defined(HAVE_BACKTRACE_CREATE_STATE)
66+
#include <backtrace.h>
67+
#elif defined(HAVE_EXECINFO_H)
6668
#include <execinfo.h>
6769
#endif
6870

@@ -1107,6 +1109,35 @@ errbacktrace(void)
11071109
return 0;
11081110
}
11091111

1112+
#ifdef HAVE_BACKTRACE_CREATE_STATE
1113+
static void
1114+
pg_backtrace_error_callback(void *data, const char *msg,
1115+
int errnum)
1116+
{
1117+
StringInfo errtrace = (StringInfo) data;
1118+
1119+
appendStringInfo(errtrace, "backtrace failure: msg: %s, errnum: %d\n", msg, errnum);
1120+
}
1121+
1122+
static int
1123+
pg_backtrace_full_callback(void *data, uintptr_t pc,
1124+
const char *filename, int lineno,
1125+
const char *function)
1126+
{
1127+
StringInfo errtrace = (StringInfo) data;
1128+
1129+
if (pc == 0xffffffffffffffff)
1130+
return 1;
1131+
1132+
appendStringInfo(errtrace, "[%p] %s: %s:%d\n",
1133+
(void *) pc,
1134+
function ? function : "[unknown]",
1135+
filename ? filename : "[unknown]", lineno);
1136+
1137+
return 0;
1138+
}
1139+
#endif
1140+
11101141
/*
11111142
* Compute backtrace data and add it to the supplied ErrorData. num_skip
11121143
* specifies how many inner frames to skip. Use this to avoid showing the
@@ -1120,7 +1151,29 @@ set_backtrace(ErrorData *edata, int num_skip)
11201151

11211152
initStringInfo(&errtrace);
11221153

1123-
#ifdef HAVE_BACKTRACE_SYMBOLS
1154+
#ifdef HAVE_BACKTRACE_CREATE_STATE
1155+
{
1156+
static struct backtrace_state *state;
1157+
1158+
/*
1159+
* The state is long-lived and can't be freed. The error callback, if
1160+
* necessary, will be called while backtrace_create_state() is
1161+
* running, so it's ok to pass errtrace here.
1162+
*/
1163+
if (state == NULL)
1164+
{
1165+
state = backtrace_create_state(
1166+
NULL, /* threaded = */ false,
1167+
pg_backtrace_error_callback, &errtrace);
1168+
}
1169+
1170+
appendStringInfo(&errtrace, "\n");
1171+
backtrace_full(state, 2,
1172+
pg_backtrace_full_callback,
1173+
pg_backtrace_error_callback,
1174+
&errtrace);
1175+
}
1176+
#elif defined(HAVE_BACKTRACE_SYMBOLS)
11241177
{
11251178
void *buf[100];
11261179
int nframes;

0 commit comments

Comments
 (0)
0