]>
git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/port/stack_trace.cc
1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
6 #include "port/stack_trace.h"
8 #if defined(ROCKSDB_LITE) || \
9 !(defined(ROCKSDB_BACKTRACE) || defined(OS_MACOSX)) || defined(CYGWIN) || \
10 defined(OS_FREEBSD) || defined(OS_SOLARIS) || defined(OS_WIN)
14 namespace ROCKSDB_NAMESPACE
{
16 void InstallStackTraceHandler() {}
17 void PrintStack(int /*first_frames_to_skip*/) {}
18 void PrintAndFreeStack(void* /*callstack*/, int /*num_frames*/) {}
19 void* SaveStack(int* /*num_frames*/, int /*first_frames_to_skip*/) {
23 } // namespace ROCKSDB_NAMESPACE
35 namespace ROCKSDB_NAMESPACE
{
40 #if defined(OS_LINUX) || defined(OS_FREEBSD) || defined(OS_GNU_KFREEBSD)
41 const char* GetExecutableName() {
42 static char name
[1024];
45 snprintf(link
, sizeof(link
), "/proc/%d/exe", getpid());
46 auto read
= readlink(link
, name
, sizeof(name
) - 1);
55 void PrintStackTraceLine(const char* symbol
, void* frame
) {
56 static const char* executable
= GetExecutableName();
58 fprintf(stderr
, "%s ", symbol
);
61 // out source to addr2line, for the address translation
62 const int kLineMax
= 256;
64 snprintf(cmd
, kLineMax
, "addr2line %p -e %s -f -C 2>&1", frame
, executable
);
65 auto f
= popen(cmd
, "r");
68 while (fgets(line
, sizeof(line
), f
)) {
69 line
[strlen(line
) - 1] = 0; // remove newline
70 fprintf(stderr
, "%s\t", line
);
75 fprintf(stderr
, " %p", frame
);
78 fprintf(stderr
, "\n");
80 #elif defined(OS_MACOSX)
82 void PrintStackTraceLine(const char* symbol
, void* frame
) {
83 static int pid
= getpid();
84 // out source to atos, for the address translation
85 const int kLineMax
= 256;
87 snprintf(cmd
, kLineMax
, "xcrun atos %p -p %d 2>&1", frame
, pid
);
88 auto f
= popen(cmd
, "r");
91 while (fgets(line
, sizeof(line
), f
)) {
92 line
[strlen(line
) - 1] = 0; // remove newline
93 fprintf(stderr
, "%s\t", line
);
97 fprintf(stderr
, "%s ", symbol
);
100 fprintf(stderr
, "\n");
107 void PrintStack(void* frames
[], int num_frames
) {
108 auto symbols
= backtrace_symbols(frames
, num_frames
);
110 for (int i
= 0; i
< num_frames
; ++i
) {
111 fprintf(stderr
, "#%-2d ", i
);
112 PrintStackTraceLine((symbols
!= nullptr) ? symbols
[i
] : nullptr, frames
[i
]);
117 void PrintStack(int first_frames_to_skip
) {
118 const int kMaxFrames
= 100;
119 void* frames
[kMaxFrames
];
121 auto num_frames
= backtrace(frames
, kMaxFrames
);
122 PrintStack(&frames
[first_frames_to_skip
], num_frames
- first_frames_to_skip
);
125 void PrintAndFreeStack(void* callstack
, int num_frames
) {
126 PrintStack(static_cast<void**>(callstack
), num_frames
);
130 void* SaveStack(int* num_frames
, int first_frames_to_skip
) {
131 const int kMaxFrames
= 100;
132 void* frames
[kMaxFrames
];
134 auto count
= backtrace(frames
, kMaxFrames
);
135 *num_frames
= count
- first_frames_to_skip
;
136 void* callstack
= malloc(sizeof(void*) * *num_frames
);
137 memcpy(callstack
, &frames
[first_frames_to_skip
], sizeof(void*) * *num_frames
);
141 static void StackTraceHandler(int sig
) {
142 // reset to default handler
143 signal(sig
, SIG_DFL
);
144 fprintf(stderr
, "Received signal %d (%s)\n", sig
, strsignal(sig
));
145 // skip the top three signal handler related frames
147 // re-signal to default handler (so we still get core dump if needed...)
151 void InstallStackTraceHandler() {
152 // just use the plain old signal as it's simple and sufficient
154 signal(SIGILL
, StackTraceHandler
);
155 signal(SIGSEGV
, StackTraceHandler
);
156 signal(SIGBUS
, StackTraceHandler
);
157 signal(SIGABRT
, StackTraceHandler
);
161 } // namespace ROCKSDB_NAMESPACE