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