Made the new memslap code build. Moved config.h include to the beginning of each...
[m6w6/libmemcached] / clients / ms_sigsegv.c
1 /*
2 * File: ms_sigsegv.c
3 * Author: Mingqiang Zhuang
4 *
5 * Created on March 15, 2009
6 *
7 * (c) Copyright 2009, Schooner Information Technology, Inc.
8 * http://www.schoonerinfotech.com/
9 *
10 */
11
12 #include "config.h"
13
14 #include <memory.h>
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <signal.h>
18 #include <ucontext.h>
19 #include <dlfcn.h>
20 #include <execinfo.h>
21 #include <pthread.h>
22
23 #include "ms_memslap.h"
24 #include "ms_setting.h"
25
26 #define NO_CPP_DEMANGLE
27 #ifndef NO_CPP_DEMANGLE
28 # include <cxxabi.h>
29 #endif
30
31 #undef REG_RIP
32
33 #if defined(REG_RIP)
34 # define SIGSEGV_STACK_IA64
35 # define REGFORMAT "%016lx"
36 #elif defined(REG_EIP)
37 # define SIGSEGV_STACK_X86
38 # define REGFORMAT "%08x"
39 #else
40 # define SIGSEGV_STACK_GENERIC
41 # define REGFORMAT "%x"
42 #endif
43
44 /* prototypes */
45 int ms_setup_sigsegv(void);
46 int ms_setup_sigpipe(void);
47 int ms_setup_sigint(void);
48
49
50 /* signal seg reaches, this function will run */
51 static void ms_signal_segv(int signum, siginfo_t *info, void *ptr)
52 {
53 int i;
54
55 UNUSED_ARGUMENT(signum);
56 UNUSED_ARGUMENT(info);
57 UNUSED_ARGUMENT(ptr);
58
59 pthread_mutex_lock(&ms_global.quit_mutex);
60 fprintf(stderr, "Segmentation fault occurred.\n");
61
62 #if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64)
63 int f= 0;
64 Dl_info dlinfo;
65 void **bp= 0;
66 void *ip= 0;
67 #else
68 void *bt[20];
69 char **strings;
70 int sz;
71 #endif
72
73 #if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64)
74 # if defined(SIGSEGV_STACK_IA64)
75 ip= (void *)ucontext->uc_mcontext.gregs[REG_RIP];
76 bp= (void **)ucontext->uc_mcontext.gregs[REG_RBP];
77 # elif defined(SIGSEGV_STACK_X86)
78 ip= (void *)ucontext->uc_mcontext.gregs[REG_EIP];
79 bp= (void **)ucontext->uc_mcontext.gregs[REG_EBP];
80 # endif
81
82 fprintf(stderr, "Stack trace:\n");
83 while (bp && ip)
84 {
85 if (! dladdr(ip, &dlinfo))
86 break;
87
88 const char *symname= dlinfo.dli_sname;
89 # ifndef NO_CPP_DEMANGLE
90 int status;
91 char *tmp= __cxa_demangle(symname, NULL, 0, &status);
92
93 if ((status == 0) && tmp)
94 symname= tmp;
95 # endif
96
97 fprintf(stderr, "% 2d: %p <%s+%u> (%s)\n",
98 ++f,
99 ip,
100 symname,
101 (unsigned)(ip - dlinfo.dli_saddr),
102 dlinfo.dli_fname);
103
104 # ifndef NO_CPP_DEMANGLE
105 if (tmp)
106 free(tmp);
107 # endif
108
109 if (dlinfo.dli_sname && ! strcmp(dlinfo.dli_sname, "main"))
110 break;
111
112 ip= bp[1];
113 bp= (void **)bp[0];
114 }
115 #else
116 fprintf(stderr, "Stack trace:\n");
117 sz= backtrace(bt, 20);
118 strings= backtrace_symbols(bt, sz);
119
120 for (i= 0; i < sz; ++i)
121 {
122 fprintf(stderr, "%s\n", strings[i]);
123 }
124 #endif
125 fprintf(stderr, "End of stack trace\n");
126 pthread_mutex_unlock(&ms_global.quit_mutex);
127 exit(1);
128 } /* ms_signal_segv */
129
130
131 /* signal pipe reaches, this function will run */
132 static void ms_signal_pipe(int signum, siginfo_t *info, void *ptr)
133 {
134 UNUSED_ARGUMENT(signum);
135 UNUSED_ARGUMENT(info);
136 UNUSED_ARGUMENT(ptr);
137
138 pthread_mutex_lock(&ms_global.quit_mutex);
139 fprintf(stderr, "\tMemslap encountered a server error. Quitting...\n");
140 fprintf(stderr, "\tError info: SIGPIPE captured (from write?)\n");
141 fprintf(stderr,
142 "\tProbably a socket I/O error when the server is down.\n");
143 pthread_mutex_unlock(&ms_global.quit_mutex);
144 exit(1);
145 } /* ms_signal_pipe */
146
147
148 /* signal int reaches, this function will run */
149 static void ms_signal_int(int signum, siginfo_t *info, void *ptr)
150 {
151 UNUSED_ARGUMENT(signum);
152 UNUSED_ARGUMENT(info);
153 UNUSED_ARGUMENT(ptr);
154
155 pthread_mutex_lock(&ms_global.quit_mutex);
156 fprintf(stderr, "SIGINT handled.\n");
157 pthread_mutex_unlock(&ms_global.quit_mutex);
158 exit(1);
159 } /* ms_signal_int */
160
161
162 /**
163 * redirect signal seg
164 *
165 * @return if success, return 0, else return -1
166 */
167 int ms_setup_sigsegv(void)
168 {
169 struct sigaction action;
170
171 memset(&action, 0, sizeof(action));
172 action.sa_sigaction= ms_signal_segv;
173 action.sa_flags= SA_SIGINFO;
174 if (sigaction(SIGSEGV, &action, NULL) < 0)
175 {
176 perror("sigaction");
177 return 0;
178 }
179
180 return -1;
181 } /* ms_setup_sigsegv */
182
183
184 /**
185 * redirect signal pipe
186 *
187 * @return if success, return 0, else return -1
188 */
189 int ms_setup_sigpipe(void)
190 {
191 struct sigaction action_2;
192
193 memset(&action_2, 0, sizeof(action_2));
194 action_2.sa_sigaction= ms_signal_pipe;
195 action_2.sa_flags= SA_SIGINFO;
196 if (sigaction(SIGPIPE, &action_2, NULL) < 0)
197 {
198 perror("sigaction");
199 return 0;
200 }
201
202 return -1;
203 } /* ms_setup_sigpipe */
204
205
206 /**
207 * redirect signal int
208 *
209 * @return if success, return 0, else return -1
210 */
211 int ms_setup_sigint(void)
212 {
213 struct sigaction action_3;
214
215 memset(&action_3, 0, sizeof(action_3));
216 action_3.sa_sigaction= ms_signal_int;
217 action_3.sa_flags= SA_SIGINFO;
218 if (sigaction(SIGINT, &action_3, NULL) < 0)
219 {
220 perror("sigaction");
221 return 0;
222 }
223
224 return -1;
225 } /* ms_setup_sigint */
226
227
228 #ifndef SIGSEGV_NO_AUTO_INIT
229 static void __attribute((constructor)) ms_init(void)
230 {
231 ms_setup_sigsegv();
232 ms_setup_sigpipe();
233 ms_setup_sigint();
234 }
235 #endif