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