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