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