Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 172 lines (149 sloc) 4.504 kB
bec59df ip address stamping and other handy changes
ttung authored
1 /**
2 * This source file is used to print out a stack-trace when your program
3 * segfaults. It is relatively reliable and spot-on accurate.
4 *
5 * This code is in the public domain. Use it as you see fit, some credit
6 * would be appreciated, but is not a prerequisite for usage. Feedback
7 * on it's use would encourage further development and maintenance.
8 *
9 * Author: Jaco Kroon <jaco@kroon.co.za>
10 *
11 * Copyright (C) 2005 - 2006 Jaco Kroon
12 */
13 #define _GNU_SOURCE
14 #include <memory.h>
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <signal.h>
18 #include <ucontext.h>
19 #include <dlfcn.h>
68d5f2e timestamp memcached k:v pairs
ttung authored
20 #if defined(HAVE_EXECINFO_H)
bec59df ip address stamping and other handy changes
ttung authored
21 #include <execinfo.h>
68d5f2e timestamp memcached k:v pairs
ttung authored
22 #endif /* #if defined(HAVE_EXECINFO_H) */
bec59df ip address stamping and other handy changes
ttung authored
23 #ifndef NO_CPP_DEMANGLE
24 #include <cxxabi.h>
25 #endif
26 #include <syslog.h>
27
28 #if defined(REG_RIP)
29 # define SIGSEGV_STACK_IA64
30 # define REGFORMAT "%016lx"
31 #elif defined(REG_EIP)
32 # define SIGSEGV_STACK_X86
33 # define REGFORMAT "%08x"
34 #else
35 # define SIGSEGV_STACK_GENERIC
36 # define REGFORMAT "%lx"
37 #endif
38
39 static void signal_segv(int signum, siginfo_t* info, void*ptr) {
40 size_t i;
ece7c31 cq_peek shouldn't decrement count if there's nothing to dequeue
ttung authored
41 #if defined(NGREG)
bec59df ip address stamping and other handy changes
ttung authored
42 ucontext_t *ucontext = (ucontext_t*)ptr;
ece7c31 cq_peek shouldn't decrement count if there's nothing to dequeue
ttung authored
43 #endif /* #if defined(NGREG) */
bec59df ip address stamping and other handy changes
ttung authored
44
45 #if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64)
46 int f = 0;
47 Dl_info dlinfo;
48 void **bp = 0;
49 void *ip = 0;
50 #endif
68d5f2e timestamp memcached k:v pairs
ttung authored
51 #if defined(HAVE_EXECINFO_H)
bec59df ip address stamping and other handy changes
ttung authored
52 void *bt[20];
53 char **strings;
54 size_t sz;
68d5f2e timestamp memcached k:v pairs
ttung authored
55 #endif /* #if defined(HAVE_EXECINFO_H) */
bec59df ip address stamping and other handy changes
ttung authored
56
57 openlog("memcached", LOG_PID, LOG_LOCAL0);
58
59 syslog(LOG_ALERT, "Segmentation Fault!\n");
60 syslog(LOG_ALERT, "info.si_signo = %d\n", signum);
61 syslog(LOG_ALERT, "info.si_errno = %d\n", info->si_errno);
62 syslog(LOG_ALERT, "info.si_code = %d\n", info->si_code);
63 syslog(LOG_ALERT, "info.si_addr = %p\n", info->si_addr);
ece7c31 cq_peek shouldn't decrement count if there's nothing to dequeue
ttung authored
64 #if defined(NGREG)
bec59df ip address stamping and other handy changes
ttung authored
65 for(i = 0; i < NGREG; i++)
66 syslog(LOG_ALERT, "reg[%02lu] = 0x" REGFORMAT "\n", i, ucontext->uc_mcontext.gregs[i]);
ece7c31 cq_peek shouldn't decrement count if there's nothing to dequeue
ttung authored
67 #endif /* #if defined(NGREG) */
bec59df ip address stamping and other handy changes
ttung authored
68
69 #if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64)
70 # if defined(SIGSEGV_STACK_IA64)
71 ip = (void*)ucontext->uc_mcontext.gregs[REG_RIP];
72 bp = (void**)ucontext->uc_mcontext.gregs[REG_RBP];
73 # elif defined(SIGSEGV_STACK_X86)
74 ip = (void*)ucontext->uc_mcontext.gregs[REG_EIP];
75 bp = (void**)ucontext->uc_mcontext.gregs[REG_EBP];
76 # endif
77
78 syslog(LOG_ALERT, "Stack trace:\n");
79 while(ip) {
80 if(!dladdr(ip, &dlinfo))
81 break;
82
83 const char *symname = dlinfo.dli_sname;
84 #ifndef NO_CPP_DEMANGLE
85 int status;
86 char *tmp = __cxa_demangle(symname, NULL, 0, &status);
87
88 if(status == 0 && tmp)
89 symname = tmp;
90 #endif
91
92 syslog(LOG_ALERT, "% 2d: %p <%s+%u> (%s)\n",
93 ++f,
94 ip,
95 symname,
96 (unsigned)(ip - dlinfo.dli_saddr),
97 dlinfo.dli_fname);
98
99 #ifndef NO_CPP_DEMANGLE
100 if(tmp)
101 free(tmp);
102 #endif
103
104 if (bp == NULL) {
105 break;
106 }
107
108 if(dlinfo.dli_sname && !strcmp(dlinfo.dli_sname, "main"))
109 break;
110
111 ip = bp[1];
112 bp = (void**)bp[0];
113 }
114 #endif
115 syslog(LOG_ALERT, "End of stack trace\n");
116 closelog();
117
68d5f2e timestamp memcached k:v pairs
ttung authored
118 #if defined(HAVE_EXECINFO_H)
bec59df ip address stamping and other handy changes
ttung authored
119 openlog("memcached", LOG_PID, LOG_LOCAL0);
120 syslog(LOG_ALERT, "Stack trace (non-dedicated):\n");
121 sz = backtrace(bt, 20);
122 strings = backtrace_symbols(bt, sz);
123
124 for(i = 0; i < sz; ++i)
125 syslog(LOG_ALERT, "%s\n", strings[i]);
126
127 syslog(LOG_ALERT, "End of stack trace (non-dedicated)\n");
128 closelog();
68d5f2e timestamp memcached k:v pairs
ttung authored
129 #endif /* #if defined(HAVE_EXECINFO_H) */
130
131 (void) i; /* consume i so we don't get a compiler warning. */
bec59df ip address stamping and other handy changes
ttung authored
132
133 exit (-1);
134 }
135
136 int setup_sigsegv() {
137 struct sigaction action;
138 memset(&action, 0, sizeof(action));
139 action.sa_sigaction = signal_segv;
140 action.sa_flags = SA_SIGINFO;
141 if(sigaction(SIGABRT, &action, NULL) < 0) {
142 perror("sigaction");
143 return 0;
144 }
145 if(sigaction(SIGBUS, &action, NULL) < 0) {
146 perror("sigaction");
147 return 0;
148 }
149 if(sigaction(SIGFPE, &action, NULL) < 0) {
150 perror("sigaction");
151 return 0;
152 }
153 if(sigaction(SIGILL, &action, NULL) < 0) {
154 perror("sigaction");
155 return 0;
156 }
157 if(sigaction(SIGSEGV, &action, NULL) < 0) {
158 perror("sigaction");
159 return 0;
160 }
161
162 return 1;
163 }
164
165 #if 0
166 #ifndef SIGSEGV_NO_AUTO_INIT
167 static void __attribute((constructor)) init(void) {
168 setup_sigsegv();
169 }
170 #endif
171 #endif /* #if 0 */
Something went wrong with that request. Please try again.