Merge pull request #74 from yoshisatoyanagisawa/fix_sigabrt_action
[platform/upstream/glog.git] / src / signalhandler.cc
1 // Copyright (c) 2008, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //     * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 //     * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 //     * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Satoru Takabayashi
31 //
32 // Implementation of InstallFailureSignalHandler().
33
34 #include "utilities.h"
35 #include "stacktrace.h"
36 #include "symbolize.h"
37 #include "glog/logging.h"
38
39 #include <signal.h>
40 #include <time.h>
41 #ifdef HAVE_UCONTEXT_H
42 # include <ucontext.h>
43 #endif
44 #ifdef HAVE_SYS_UCONTEXT_H
45 # include <sys/ucontext.h>
46 #endif
47 #include <algorithm>
48
49 _START_GOOGLE_NAMESPACE_
50
51 // TOOD(hamaji): Use signal instead of sigaction?
52 #ifdef HAVE_SIGACTION
53
54 namespace {
55
56 // We'll install the failure signal handler for these signals.  We could
57 // use strsignal() to get signal names, but we don't use it to avoid
58 // introducing yet another #ifdef complication.
59 //
60 // The list should be synced with the comment in signalhandler.h.
61 const struct {
62   int number;
63   const char *name;
64 } kFailureSignals[] = {
65   { SIGSEGV, "SIGSEGV" },
66   { SIGILL, "SIGILL" },
67   { SIGFPE, "SIGFPE" },
68   { SIGABRT, "SIGABRT" },
69   { SIGBUS, "SIGBUS" },
70   { SIGTERM, "SIGTERM" },
71 };
72
73 // Returns the program counter from signal context, NULL if unknown.
74 void* GetPC(void* ucontext_in_void) {
75 #if (defined(HAVE_UCONTEXT_H) || defined(HAVE_SYS_UCONTEXT_H)) && defined(PC_FROM_UCONTEXT)
76   if (ucontext_in_void != NULL) {
77     ucontext_t *context = reinterpret_cast<ucontext_t *>(ucontext_in_void);
78     return (void*)context->PC_FROM_UCONTEXT;
79   }
80 #endif
81   return NULL;
82 }
83
84 // The class is used for formatting error messages.  We don't use printf()
85 // as it's not async signal safe.
86 class MinimalFormatter {
87  public:
88   MinimalFormatter(char *buffer, int size)
89       : buffer_(buffer),
90         cursor_(buffer),
91         end_(buffer + size) {
92   }
93
94   // Returns the number of bytes written in the buffer.
95   int num_bytes_written() const { return cursor_ - buffer_; }
96
97   // Appends string from "str" and updates the internal cursor.
98   void AppendString(const char* str) {
99     int i = 0;
100     while (str[i] != '\0' && cursor_ + i < end_) {
101       cursor_[i] = str[i];
102       ++i;
103     }
104     cursor_ += i;
105   }
106
107   // Formats "number" in "radix" and updates the internal cursor.
108   // Lowercase letters are used for 'a' - 'z'.
109   void AppendUint64(uint64 number, int radix) {
110     int i = 0;
111     while (cursor_ + i < end_) {
112       const int tmp = number % radix;
113       number /= radix;
114       cursor_[i] = (tmp < 10 ? '0' + tmp : 'a' + tmp - 10);
115       ++i;
116       if (number == 0) {
117         break;
118       }
119     }
120     // Reverse the bytes written.
121     std::reverse(cursor_, cursor_ + i);
122     cursor_ += i;
123   }
124
125   // Formats "number" as hexadecimal number, and updates the internal
126   // cursor.  Padding will be added in front if needed.
127   void AppendHexWithPadding(uint64 number, int width) {
128     char* start = cursor_;
129     AppendString("0x");
130     AppendUint64(number, 16);
131     // Move to right and add padding in front if needed.
132     if (cursor_ < start + width) {
133       const int64 delta = start + width - cursor_;
134       std::copy(start, cursor_, start + delta);
135       std::fill(start, start + delta, ' ');
136       cursor_ = start + width;
137     }
138   }
139
140  private:
141   char *buffer_;
142   char *cursor_;
143   const char * const end_;
144 };
145
146 // Writes the given data with the size to the standard error.
147 void WriteToStderr(const char* data, int size) {
148   if (write(STDERR_FILENO, data, size) < 0) {
149     // Ignore errors.
150   }
151 }
152
153 // The writer function can be changed by InstallFailureWriter().
154 void (*g_failure_writer)(const char* data, int size) = WriteToStderr;
155
156 // Dumps time information.  We don't dump human-readable time information
157 // as localtime() is not guaranteed to be async signal safe.
158 void DumpTimeInfo() {
159   time_t time_in_sec = time(NULL);
160   char buf[256];  // Big enough for time info.
161   MinimalFormatter formatter(buf, sizeof(buf));
162   formatter.AppendString("*** Aborted at ");
163   formatter.AppendUint64(time_in_sec, 10);
164   formatter.AppendString(" (unix time)");
165   formatter.AppendString(" try \"date -d @");
166   formatter.AppendUint64(time_in_sec, 10);
167   formatter.AppendString("\" if you are using GNU date ***\n");
168   g_failure_writer(buf, formatter.num_bytes_written());
169 }
170
171 // Dumps information about the signal to STDERR.
172 void DumpSignalInfo(int signal_number, siginfo_t *siginfo) {
173   // Get the signal name.
174   const char* signal_name = NULL;
175   for (size_t i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
176     if (signal_number == kFailureSignals[i].number) {
177       signal_name = kFailureSignals[i].name;
178     }
179   }
180
181   char buf[256];  // Big enough for signal info.
182   MinimalFormatter formatter(buf, sizeof(buf));
183
184   formatter.AppendString("*** ");
185   if (signal_name) {
186     formatter.AppendString(signal_name);
187   } else {
188     // Use the signal number if the name is unknown.  The signal name
189     // should be known, but just in case.
190     formatter.AppendString("Signal ");
191     formatter.AppendUint64(signal_number, 10);
192   }
193   formatter.AppendString(" (@0x");
194   formatter.AppendUint64(reinterpret_cast<uintptr_t>(siginfo->si_addr), 16);
195   formatter.AppendString(")");
196   formatter.AppendString(" received by PID ");
197   formatter.AppendUint64(getpid(), 10);
198   formatter.AppendString(" (TID 0x");
199   // We assume pthread_t is an integral number or a pointer, rather
200   // than a complex struct.  In some environments, pthread_self()
201   // returns an uint64 but in some other environments pthread_self()
202   // returns a pointer.  Hence we use C-style cast here, rather than
203   // reinterpret/static_cast, to support both types of environments.
204   formatter.AppendUint64((uintptr_t)pthread_self(), 16);
205   formatter.AppendString(") ");
206   // Only linux has the PID of the signal sender in si_pid.
207 #ifdef OS_LINUX
208   formatter.AppendString("from PID ");
209   formatter.AppendUint64(siginfo->si_pid, 10);
210   formatter.AppendString("; ");
211 #endif
212   formatter.AppendString("stack trace: ***\n");
213   g_failure_writer(buf, formatter.num_bytes_written());
214 }
215
216 // Dumps information about the stack frame to STDERR.
217 void DumpStackFrameInfo(const char* prefix, void* pc) {
218   // Get the symbol name.
219   const char *symbol = "(unknown)";
220   char symbolized[1024];  // Big enough for a sane symbol.
221   // Symbolizes the previous address of pc because pc may be in the
222   // next function.
223   if (Symbolize(reinterpret_cast<char *>(pc) - 1,
224                 symbolized, sizeof(symbolized))) {
225     symbol = symbolized;
226   }
227
228   char buf[1024];  // Big enough for stack frame info.
229   MinimalFormatter formatter(buf, sizeof(buf));
230
231   formatter.AppendString(prefix);
232   formatter.AppendString("@ ");
233   const int width = 2 * sizeof(void*) + 2;  // + 2  for "0x".
234   formatter.AppendHexWithPadding(reinterpret_cast<uintptr_t>(pc), width);
235   formatter.AppendString(" ");
236   formatter.AppendString(symbol);
237   formatter.AppendString("\n");
238   g_failure_writer(buf, formatter.num_bytes_written());
239 }
240
241 // Invoke the default signal handler.
242 void InvokeDefaultSignalHandler(int signal_number) {
243   struct sigaction sig_action;
244   memset(&sig_action, 0, sizeof(sig_action));
245   sigemptyset(&sig_action.sa_mask);
246   sig_action.sa_handler = SIG_DFL;
247   sigaction(signal_number, &sig_action, NULL);
248   kill(getpid(), signal_number);
249 }
250
251 // This variable is used for protecting FailureSignalHandler() from
252 // dumping stuff while another thread is doing it.  Our policy is to let
253 // the first thread dump stuff and let other threads wait.
254 // See also comments in FailureSignalHandler().
255 static pthread_t* g_entered_thread_id_pointer = NULL;
256
257 // Dumps signal and stack frame information, and invokes the default
258 // signal handler once our job is done.
259 void FailureSignalHandler(int signal_number,
260                           siginfo_t *signal_info,
261                           void *ucontext) {
262   // First check if we've already entered the function.  We use an atomic
263   // compare and swap operation for platforms that support it.  For other
264   // platforms, we use a naive method that could lead to a subtle race.
265
266   // We assume pthread_self() is async signal safe, though it's not
267   // officially guaranteed.
268   pthread_t my_thread_id = pthread_self();
269   // NOTE: We could simply use pthread_t rather than pthread_t* for this,
270   // if pthread_self() is guaranteed to return non-zero value for thread
271   // ids, but there is no such guarantee.  We need to distinguish if the
272   // old value (value returned from __sync_val_compare_and_swap) is
273   // different from the original value (in this case NULL).
274   pthread_t* old_thread_id_pointer =
275       glog_internal_namespace_::sync_val_compare_and_swap(
276           &g_entered_thread_id_pointer,
277           static_cast<pthread_t*>(NULL),
278           &my_thread_id);
279   if (old_thread_id_pointer != NULL) {
280     // We've already entered the signal handler.  What should we do?
281     if (pthread_equal(my_thread_id, *g_entered_thread_id_pointer)) {
282       // It looks the current thread is reentering the signal handler.
283       // Something must be going wrong (maybe we are reentering by another
284       // type of signal?).  Kill ourself by the default signal handler.
285       InvokeDefaultSignalHandler(signal_number);
286     }
287     // Another thread is dumping stuff.  Let's wait until that thread
288     // finishes the job and kills the process.
289     while (true) {
290       sleep(1);
291     }
292   }
293   // This is the first time we enter the signal handler.  We are going to
294   // do some interesting stuff from here.
295   // TODO(satorux): We might want to set timeout here using alarm(), but
296   // mixing alarm() and sleep() can be a bad idea.
297
298   // First dump time info.
299   DumpTimeInfo();
300
301   // Get the program counter from ucontext.
302   void *pc = GetPC(ucontext);
303   DumpStackFrameInfo("PC: ", pc);
304
305 #ifdef HAVE_STACKTRACE
306   // Get the stack traces.
307   void *stack[32];
308   // +1 to exclude this function.
309   const int depth = GetStackTrace(stack, ARRAYSIZE(stack), 1);
310   DumpSignalInfo(signal_number, signal_info);
311   // Dump the stack traces.
312   for (int i = 0; i < depth; ++i) {
313     DumpStackFrameInfo("    ", stack[i]);
314   }
315 #endif
316
317   // *** TRANSITION ***
318   //
319   // BEFORE this point, all code must be async-termination-safe!
320   // (See WARNING above.)
321   //
322   // AFTER this point, we do unsafe things, like using LOG()!
323   // The process could be terminated or hung at any time.  We try to
324   // do more useful things first and riskier things later.
325
326   // Flush the logs before we do anything in case 'anything'
327   // causes problems.
328   FlushLogFilesUnsafe(0);
329
330   // Kill ourself by the default signal handler.
331   InvokeDefaultSignalHandler(signal_number);
332 }
333
334 }  // namespace
335
336 #endif  // HAVE_SIGACTION
337
338 namespace glog_internal_namespace_ {
339
340 bool IsFailureSignalHandlerInstalled() {
341 #ifdef HAVE_SIGACTION
342   struct sigaction sig_action;
343   memset(&sig_action, 0, sizeof(sig_action));
344   sigemptyset(&sig_action.sa_mask);
345   sigaction(SIGABRT, NULL, &sig_action);
346   if (sig_action.sa_sigaction == &FailureSignalHandler)
347     return true;
348 #endif  // HAVE_SIGACTION
349   return false;
350 }
351
352 }  // namespace glog_internal_namespace_
353
354 void InstallFailureSignalHandler() {
355 #ifdef HAVE_SIGACTION
356   // Build the sigaction struct.
357   struct sigaction sig_action;
358   memset(&sig_action, 0, sizeof(sig_action));
359   sigemptyset(&sig_action.sa_mask);
360   sig_action.sa_flags |= SA_SIGINFO;
361   sig_action.sa_sigaction = &FailureSignalHandler;
362
363   for (size_t i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
364     CHECK_ERR(sigaction(kFailureSignals[i].number, &sig_action, NULL));
365   }
366 #endif  // HAVE_SIGACTION
367 }
368
369 void InstallFailureWriter(void (*writer)(const char* data, int size)) {
370 #ifdef HAVE_SIGACTION
371   g_failure_writer = writer;
372 #endif  // HAVE_SIGACTION
373 }
374
375 _END_GOOGLE_NAMESPACE_