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