Update comments in get_interface_addresses_ioctl
[tor.git] / src / common / backtrace.c
bloba2d5378b204e50d08ba80067e30a23210637add1
1 /* Copyright (c) 2013-2015, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 #define __USE_GNU
5 #define _GNU_SOURCE 1
7 #include "orconfig.h"
8 #include "compat.h"
9 #include "util.h"
10 #include "torlog.h"
12 #ifdef HAVE_EXECINFO_H
13 #include <execinfo.h>
14 #endif
15 #ifdef HAVE_FCNTL_H
16 #include <fcntl.h>
17 #endif
18 #ifdef HAVE_UNISTD_H
19 #include <unistd.h>
20 #endif
21 #ifdef HAVE_SIGNAL_H
22 #include <signal.h>
23 #endif
25 #ifdef HAVE_CYGWIN_SIGNAL_H
26 #include <cygwin/signal.h>
27 #elif defined(HAVE_SYS_UCONTEXT_H)
28 #include <sys/ucontext.h>
29 #elif defined(HAVE_UCONTEXT_H)
30 #include <ucontext.h>
31 #endif
33 #define EXPOSE_CLEAN_BACKTRACE
34 #include "backtrace.h"
36 #if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
37 defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
38 #define USE_BACKTRACE
39 #endif
41 #if !defined(USE_BACKTRACE)
42 #define NO_BACKTRACE_IMPL
43 #endif
45 /** Version of Tor to report in backtrace messages. */
46 static char *bt_version = NULL;
48 #ifdef USE_BACKTRACE
49 /** Largest stack depth to try to dump. */
50 #define MAX_DEPTH 256
51 /** Static allocation of stack to dump. This is static so we avoid stack
52 * pressure. */
53 static void *cb_buf[MAX_DEPTH];
54 /** Protects cb_buf from concurrent access */
55 static tor_mutex_t cb_buf_mutex;
57 /** Change a stacktrace in <b>stack</b> of depth <b>depth</b> so that it will
58 * log the correct function from which a signal was received with context
59 * <b>ctx</b>. (When we get a signal, the current function will not have
60 * called any other function, and will therefore have not pushed its address
61 * onto the stack. Fortunately, we usually have the program counter in the
62 * ucontext_t structure.
64 void
65 clean_backtrace(void **stack, int depth, const ucontext_t *ctx)
67 #ifdef PC_FROM_UCONTEXT
68 #if defined(__linux__)
69 const int n = 1;
70 #elif defined(__darwin__) || defined(__APPLE__) || defined(__OpenBSD__) \
71 || defined(__FreeBSD__)
72 const int n = 2;
73 #else
74 const int n = 1;
75 #endif
76 if (depth <= n)
77 return;
79 stack[n] = (void*) ctx->PC_FROM_UCONTEXT;
80 #else
81 (void) depth;
82 (void) ctx;
83 (void) stack;
84 #endif
87 /** Log a message <b>msg</b> at <b>severity</b> in <b>domain</b>, and follow
88 * that with a backtrace log. */
89 void
90 log_backtrace(int severity, int domain, const char *msg)
92 int depth;
93 char **symbols;
94 int i;
96 tor_mutex_acquire(&cb_buf_mutex);
98 depth = backtrace(cb_buf, MAX_DEPTH);
99 symbols = backtrace_symbols(cb_buf, depth);
101 tor_log(severity, domain, "%s. Stack trace:", msg);
102 if (!symbols) {
103 tor_log(severity, domain, " Unable to generate backtrace.");
104 goto done;
106 for (i=0; i < depth; ++i) {
107 tor_log(severity, domain, " %s", symbols[i]);
109 free(symbols);
111 done:
112 tor_mutex_release(&cb_buf_mutex);
115 static void crash_handler(int sig, siginfo_t *si, void *ctx_)
116 __attribute__((noreturn));
118 /** Signal handler: write a crash message with a stack trace, and die. */
119 static void
120 crash_handler(int sig, siginfo_t *si, void *ctx_)
122 char buf[40];
123 int depth;
124 ucontext_t *ctx = (ucontext_t *) ctx_;
125 int n_fds, i;
126 const int *fds = NULL;
128 (void) si;
130 depth = backtrace(cb_buf, MAX_DEPTH);
131 /* Clean up the top stack frame so we get the real function
132 * name for the most recently failing function. */
133 clean_backtrace(cb_buf, depth, ctx);
135 format_dec_number_sigsafe((unsigned)sig, buf, sizeof(buf));
137 tor_log_err_sigsafe(bt_version, " died: Caught signal ", buf, "\n",
138 NULL);
140 n_fds = tor_log_get_sigsafe_err_fds(&fds);
141 for (i=0; i < n_fds; ++i)
142 backtrace_symbols_fd(cb_buf, depth, fds[i]);
144 abort();
147 /** Install signal handlers as needed so that when we crash, we produce a
148 * useful stack trace. Return 0 on success, -1 on failure. */
149 static int
150 install_bt_handler(void)
152 int trap_signals[] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS, SIGSYS,
153 SIGIO, -1 };
154 int i, rv=0;
156 struct sigaction sa;
158 tor_mutex_init(&cb_buf_mutex);
160 memset(&sa, 0, sizeof(sa));
161 sa.sa_sigaction = crash_handler;
162 sa.sa_flags = SA_SIGINFO;
163 sigfillset(&sa.sa_mask);
165 for (i = 0; trap_signals[i] >= 0; ++i) {
166 if (sigaction(trap_signals[i], &sa, NULL) == -1) {
167 log_warn(LD_BUG, "Sigaction failed: %s", strerror(errno));
168 rv = -1;
173 /* Now, generate (but do not log) a backtrace. This ensures that
174 * libc has pre-loaded the symbols we need to dump things, so that later
175 * reads won't be denied by the sandbox code */
176 char **symbols;
177 int depth = backtrace(cb_buf, MAX_DEPTH);
178 symbols = backtrace_symbols(cb_buf, depth);
179 if (symbols)
180 free(symbols);
183 return rv;
186 /** Uninstall crash handlers. */
187 static void
188 remove_bt_handler(void)
190 tor_mutex_uninit(&cb_buf_mutex);
192 #endif
194 #ifdef NO_BACKTRACE_IMPL
195 void
196 log_backtrace(int severity, int domain, const char *msg)
198 tor_log(severity, domain, "%s. (Stack trace not available)", msg);
201 static int
202 install_bt_handler(void)
204 return 0;
207 static void
208 remove_bt_handler(void)
211 #endif
213 /** Set up code to handle generating error messages on crashes. */
215 configure_backtrace_handler(const char *tor_version)
217 tor_free(bt_version);
218 if (!tor_version)
219 tor_version = "";
220 tor_asprintf(&bt_version, "Tor %s", tor_version);
222 return install_bt_handler();
225 /** Perform end-of-process cleanup for code that generates error messages on
226 * crashes. */
227 void
228 clean_up_backtrace_handler(void)
230 remove_bt_handler();
232 tor_free(bt_version);