Utilize the second parameter (version number) for deb.sh.
[platform/upstream/glog.git] / src / signalhandler.cc
1 // Copyright 2008 Google Inc. All Rights Reserved.
2 // Author: Satoru Takabayashi
3 //
4 // Implementation of InstallFailureSignalHandler().
5
6 #include "utilities.h"
7 #include "stacktrace.h"
8 #include "symbolize.h"
9 #include "glog/logging.h"
10
11 #include <signal.h>
12 #include <time.h>
13 #ifdef HAVE_UCONTEXT_H
14 # include <ucontext.h>
15 #endif
16 #include <algorithm>
17
18 _START_GOOGLE_NAMESPACE_
19
20 // There is a better way, but this is good enough in this file.
21 #define NAIVE_ARRAYSIZE(a) (sizeof(a) / sizeof(*(a)))
22
23 namespace {
24
25 // Wrapper of __sync_val_compare_and_swap. If the GCC extension isn't
26 // defined, we try the CPU specific logics (we only support x86 and
27 // x86_64 for now) first, then use a naive implementation, which has a
28 // race condition.
29 template<typename T>
30 inline T* sync_val_compare_and_swap(T** ptr, T* oldval, T* newval) {
31 #if defined(HAVE___SYNC_VAL_COMPARE_AND_SWAP)
32   return __sync_val_compare_and_swap(ptr, oldval, newval);
33 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
34   T* ret;
35   __asm__ __volatile__("lock; cmpxchg %1, (%2);"
36                        :"=a"(ret)
37                        :"r"(newval), "r"(ptr), "a"(oldval)
38                        :"memory", "cc");
39   return ret;
40 #else
41   T* ret = *ptr;
42   if (ret == oldval) {
43     *ptr = newval;
44   }
45   return ret;
46 #endif
47 }
48
49 // We'll install the failure signal handler for these signals.  We could
50 // use strsignal() to get signal names, but we don't use it to avoid
51 // introducing yet another #ifdef complication.
52 //
53 // The list should be synced with the comment in signalhandler.h.
54 const struct {
55   int number;
56   const char *name;
57 } kFailureSignals[] = {
58   { SIGSEGV, "SIGSEGV" },
59   { SIGILL, "SIGILL" },
60   { SIGFPE, "SIGFPE" },
61   { SIGABRT, "SIGABRT" },
62   { SIGBUS, "SIGBUS" },
63   { SIGTERM, "SIGTERM" },
64 };
65
66 // Returns the program counter from signal context, NULL if unknown.
67 void* GetPC(void* ucontext_in_void) {
68 #if defined(HAVE_UCONTEXT_H) && defined(PC_FROM_UCONTEXT)
69   if (ucontext_in_void != NULL) {
70     ucontext_t *context = reinterpret_cast<ucontext_t *>(ucontext_in_void);
71     return (void*)context->PC_FROM_UCONTEXT;
72   }
73 #endif
74   return NULL;
75 }
76
77 // The class is used for formatting error messages.  We don't use printf()
78 // as it's not async signal safe.
79 class MinimalFormatter {
80  public:
81   MinimalFormatter(char *buffer, int size)
82       : buffer_(buffer),
83         cursor_(buffer),
84         end_(buffer + size) {
85   }
86
87   // Returns the number of bytes written in the buffer.
88   int num_bytes_written() const { return cursor_ - buffer_; }
89
90   // Appends string from "str" and updates the internal cursor.
91   void AppendString(const char* str) {
92     int i = 0;
93     while (str[i] != '\0' && cursor_ + i < end_) {
94       cursor_[i] = str[i];
95       ++i;
96     }
97     cursor_ += i;
98   }
99
100   // Formats "number" in "radix" and updates the internal cursor.
101   // Lowercase letters are used for 'a' - 'z'.
102   void AppendUint64(uint64 number, int radix) {
103     int i = 0;
104     while (cursor_ + i < end_) {
105       const int tmp = number % radix;
106       number /= radix;
107       cursor_[i] = (tmp < 10 ? '0' + tmp : 'a' + tmp - 10);
108       ++i;
109       if (number == 0) {
110         break;
111       }
112     }
113     // Reverse the bytes written.
114     std::reverse(cursor_, cursor_ + i);
115     cursor_ += i;
116   }
117
118   // Formats "number" as hexadecimal number, and updates the internal
119   // cursor.  Padding will be added in front if needed.
120   void AppendHexWithPadding(uint64 number, int width) {
121     char* start = cursor_;
122     AppendString("0x");
123     AppendUint64(number, 16);
124     // Move to right and add padding in front if needed.
125     if (cursor_ < start + width) {
126       const int64 delta = start + width - cursor_;
127       std::copy(start, cursor_, start + delta);
128       std::fill(start, start + delta, ' ');
129       cursor_ = start + width;
130     }
131   }
132
133  private:
134   char *buffer_;
135   char *cursor_;
136   const char * const end_;
137 };
138
139 // Writes the given data with the size to the standard error.
140 void WriteToStderr(const char* data, int size) {
141   write(STDERR_FILENO, data, size);
142 }
143
144 // The writer function can be changed by InstallFailureWriter().
145 void (*g_failure_writer)(const char* data, int size) = WriteToStderr;
146
147 // Dumps time information.  We don't dump human-readable time information
148 // as localtime() is not guaranteed to be async signal safe.
149 void DumpTimeInfo() {
150   time_t time_in_sec = time(NULL);
151   char buf[256];  // Big enough for time info.
152   MinimalFormatter formatter(buf, sizeof(buf));
153   formatter.AppendString("*** Aborted at ");
154   formatter.AppendUint64(time_in_sec, 10);
155   formatter.AppendString(" (unix time)");
156   formatter.AppendString(" try \"date -d @");
157   formatter.AppendUint64(time_in_sec, 10);
158   formatter.AppendString("\" if you are using GNU date ***\n");
159   g_failure_writer(buf, formatter.num_bytes_written());
160 }
161
162 // Dumps information about the signal to STDERR.
163 void DumpSignalInfo(int signal_number, siginfo_t *siginfo) {
164   // Get the signal name.
165   const char* signal_name = NULL;
166   for (int i = 0; i < NAIVE_ARRAYSIZE(kFailureSignals); ++i) {
167     if (signal_number == kFailureSignals[i].number) {
168       signal_name = kFailureSignals[i].name;
169     }
170   }
171
172   char buf[256];  // Big enough for signal info.
173   MinimalFormatter formatter(buf, sizeof(buf));
174
175   formatter.AppendString("*** ");
176   if (signal_name) {
177     formatter.AppendString(signal_name);
178   } else {
179     // Use the signal number if the name is unknown.  The signal name
180     // should be known, but just in case.
181     formatter.AppendString("Signal ");
182     formatter.AppendUint64(signal_number, 10);
183   }
184   formatter.AppendString(" (@0x");
185   formatter.AppendUint64(reinterpret_cast<uintptr_t>(siginfo->si_addr), 16);
186   formatter.AppendString(")");
187   formatter.AppendString(" received by PID ");
188   formatter.AppendUint64(getpid(), 10);
189   formatter.AppendString(" (TID 0x");
190   // We assume pthread_t is an integral number or a pointer, rather
191   // than a complex struct.  In some environments, pthread_self()
192   // returns an uint64 but in some other environments pthread_self()
193   // returns a pointer.  Hence we use C-style cast here, rather than
194   // reinterpret/static_cast, to support both types of environments.
195   formatter.AppendUint64((uintptr_t)pthread_self(), 16);
196   formatter.AppendString(") ");
197   // Only linux has the PID of the signal sender in si_pid.
198 #ifdef OS_LINUX
199   formatter.AppendString("from PID ");
200   formatter.AppendUint64(siginfo->si_pid, 10);
201   formatter.AppendString("; ");
202 #endif
203   formatter.AppendString("stack trace: ***\n");
204   g_failure_writer(buf, formatter.num_bytes_written());
205 }
206
207 // Dumps information about the stack frame to STDERR.
208 void DumpStackFrameInfo(const char* prefix, void* pc) {
209   // Get the symbol name.
210   const char *symbol = "(unknown)";
211   char symbolized[1024];  // Big enough for a sane symbol.
212   // Symbolizes the previous address of pc because pc may be in the
213   // next function.
214   if (Symbolize(reinterpret_cast<char *>(pc) - 1,
215                 symbolized, sizeof(symbolized))) {
216     symbol = symbolized;
217   }
218
219   char buf[1024];  // Big enough for stack frame info.
220   MinimalFormatter formatter(buf, sizeof(buf));
221
222   formatter.AppendString(prefix);
223   formatter.AppendString("@ ");
224   const int width = 2 * sizeof(void*) + 2;  // + 2  for "0x".
225   formatter.AppendHexWithPadding(reinterpret_cast<uintptr_t>(pc), width);
226   formatter.AppendString(" ");
227   formatter.AppendString(symbol);
228   formatter.AppendString("\n");
229   g_failure_writer(buf, formatter.num_bytes_written());
230 }
231
232 // Invoke the default signal handler.
233 void InvokeDefaultSignalHandler(int signal_number) {
234   struct sigaction sig_action = {};  // Zero-clear.
235   sigemptyset(&sig_action.sa_mask);
236   sig_action.sa_handler = SIG_DFL;
237   sigaction(signal_number, &sig_action, NULL);
238   kill(getpid(), signal_number);
239 }
240
241 // This variable is used for protecting FailureSignalHandler() from
242 // dumping stuff while another thread is doing it.  Our policy is to let
243 // the first thread dump stuff and let other threads wait.
244 // See also comments in FailureSignalHandler().
245 static pthread_t* g_entered_thread_id_pointer = NULL;
246
247 // Dumps signal and stack frame information, and invokes the default
248 // signal handler once our job is done.
249 void FailureSignalHandler(int signal_number,
250                           siginfo_t *signal_info,
251                           void *ucontext) {
252   // First check if we've already entered the function.  We use an atomic
253   // compare and swap operation for platforms that support it.  For other
254   // platforms, we use a naive method that could lead to a subtle race.
255
256   // We assume pthread_self() is async signal safe, though it's not
257   // officially guaranteed.
258   pthread_t my_thread_id = pthread_self();
259   // NOTE: We could simply use pthread_t rather than pthread_t* for this,
260   // if pthread_self() is guaranteed to return non-zero value for thread
261   // ids, but there is no such guarantee.  We need to distinguish if the
262   // old value (value returned from __sync_val_compare_and_swap) is
263   // different from the original value (in this case NULL).
264   pthread_t* old_thread_id_pointer =
265       sync_val_compare_and_swap(&g_entered_thread_id_pointer,
266                                 static_cast<pthread_t*>(NULL),
267                                 &my_thread_id);
268   if (old_thread_id_pointer != NULL) {
269     // We've already entered the signal handler.  What should we do?
270     if (pthread_equal(my_thread_id, *g_entered_thread_id_pointer)) {
271       // It looks the current thread is reentering the signal handler.
272       // Something must be going wrong (maybe we are reentering by another
273       // type of signal?).  Kill ourself by the default signal handler.
274       InvokeDefaultSignalHandler(signal_number);
275     }
276     // Another thread is dumping stuff.  Let's wait until that thread
277     // finishes the job and kills the process.
278     while (true) {
279       sleep(1);
280     }
281   }
282   // This is the first time we enter the signal handler.  We are going to
283   // do some interesting stuff from here.
284   // TODO(satorux): We might want to set timeout here using alarm(), but
285   // mixing alarm() and sleep() can be a bad idea.
286
287   // First dump time info.
288   DumpTimeInfo();
289
290   // Get the program counter from ucontext.
291   void *pc = GetPC(ucontext);
292   DumpStackFrameInfo("PC: ", pc);
293
294 #ifdef HAVE_STACKTRACE
295   // Get the stack traces.
296   void *stack[32];
297   // +1 to exclude this function.
298   const int depth = GetStackTrace(stack, NAIVE_ARRAYSIZE(stack), 1);
299   DumpSignalInfo(signal_number, signal_info);
300   // Dump the stack traces.
301   for (int i = 0; i < depth; ++i) {
302     DumpStackFrameInfo("    ", stack[i]);
303   }
304 #endif
305   // Kill ourself by the default signal handler.
306   InvokeDefaultSignalHandler(signal_number);
307 }
308
309 }  // namespace
310
311 void InstallFailureSignalHandler() {
312   // Build the sigaction struct.
313   struct sigaction sig_action = {};  // Zero-clear.
314   sigemptyset(&sig_action.sa_mask);
315   sig_action.sa_flags |= SA_SIGINFO;
316   sig_action.sa_sigaction = &FailureSignalHandler;
317
318   for (int i = 0; i < NAIVE_ARRAYSIZE(kFailureSignals); ++i) {
319     CHECK_ERR(sigaction(kFailureSignals[i].number, &sig_action, NULL));
320   }
321 }
322
323 void InstallFailureWriter(void (*writer)(const char* data, int size)) {
324   g_failure_writer = writer;
325 }
326
327 _END_GOOGLE_NAMESPACE_