19abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// Copyright (c) 2007, Google Inc. 29abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// All rights reserved. 39abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// 49abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// Redistribution and use in source and binary forms, with or without 59abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// modification, are permitted provided that the following conditions are 69abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// met: 79abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// 89abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// * Redistributions of source code must retain the above copyright 99abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// notice, this list of conditions and the following disclaimer. 109abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// * Redistributions in binary form must reproduce the above 119abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// copyright notice, this list of conditions and the following disclaimer 129abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// in the documentation and/or other materials provided with the 139abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// distribution. 149abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// * Neither the name of Google Inc. nor the names of its 159abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// contributors may be used to endorse or promote products derived from 169abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// this software without specific prior written permission. 179abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// 189abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 199abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 209abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 219abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 229abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 239abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 249abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 259abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 269abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 279abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 289abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 299abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 309abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// Author: Alfred Peng 319abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 329abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai#include <signal.h> 339abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai#include <sys/stat.h> 349abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai#include <sys/types.h> 359abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai#include <unistd.h> 369abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 379abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai#include <cassert> 389abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai#include <cstdlib> 399abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai#include <ctime> 409abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 419abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai#include "client/solaris/handler/exception_handler.h" 429abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai#include "common/solaris/guid_creator.h" 439abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai#include "common/solaris/message_output.h" 449abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai#include "google_breakpad/common/minidump_format.h" 459abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 469abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovainamespace google_breakpad { 479abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 489abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// Signals that we are interested. 499abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovaistatic const int kSigTable[] = { 509abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai SIGSEGV, 519abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai SIGABRT, 529abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai SIGFPE, 539abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai SIGILL, 549abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai SIGBUS 559abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai}; 569abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 579abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovaistd::vector<ExceptionHandler*> *ExceptionHandler::handler_stack_ = NULL; 589abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovaiint ExceptionHandler::handler_stack_index_ = 0; 599abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovaipthread_mutex_t ExceptionHandler::handler_stack_mutex_ = 609abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai PTHREAD_MUTEX_INITIALIZER; 619abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 629abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovaiExceptionHandler::ExceptionHandler(const string &dump_path, 639abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai FilterCallback filter, 649abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai MinidumpCallback callback, 659abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai void *callback_context, 669abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai bool install_handler) 679abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai : filter_(filter), 689abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai callback_(callback), 699abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai callback_context_(callback_context), 70dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek dump_path_(), 719abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai installed_handler_(install_handler) { 729abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai set_dump_path(dump_path); 739abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 749abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai if (install_handler) { 759abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai SetupHandler(); 769abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai } 779abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 789abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai if (install_handler) { 799abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai pthread_mutex_lock(&handler_stack_mutex_); 809abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 819abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai if (handler_stack_ == NULL) 829abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai handler_stack_ = new std::vector<ExceptionHandler *>; 839abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai handler_stack_->push_back(this); 849abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai pthread_mutex_unlock(&handler_stack_mutex_); 859abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai } 869abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai} 879abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 889abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovaiExceptionHandler::~ExceptionHandler() { 899abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai TeardownAllHandlers(); 909abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai pthread_mutex_lock(&handler_stack_mutex_); 919abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai if (handler_stack_->back() == this) { 929abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai handler_stack_->pop_back(); 939abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai } else { 949abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai print_message1(2, "warning: removing Breakpad handler out of order\n"); 959abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai for (std::vector<ExceptionHandler *>::iterator iterator = 969abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai handler_stack_->begin(); 979abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai iterator != handler_stack_->end(); 989abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai ++iterator) { 999abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai if (*iterator == this) { 1009abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai handler_stack_->erase(iterator); 1019abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai } 1029abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai } 1039abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai } 1049abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 1059abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai if (handler_stack_->empty()) { 1069abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai // When destroying the last ExceptionHandler that installed a handler, 1079abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai // clean up the handler stack. 1089abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai delete handler_stack_; 1099abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai handler_stack_ = NULL; 1109abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai } 1119abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai pthread_mutex_unlock(&handler_stack_mutex_); 1129abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai} 1139abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 1149abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovaibool ExceptionHandler::WriteMinidump() { 115dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek return InternalWriteMinidump(0, 0, NULL); 1169abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai} 1179abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 1189abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// static 1199abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovaibool ExceptionHandler::WriteMinidump(const string &dump_path, 1209abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai MinidumpCallback callback, 1219abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai void *callback_context) { 1229abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai ExceptionHandler handler(dump_path, NULL, callback, 1239abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai callback_context, false); 124dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek return handler.InternalWriteMinidump(0, 0, NULL); 1259abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai} 1269abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 1279abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovaivoid ExceptionHandler::SetupHandler() { 1289abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai // Signal on a different stack to avoid using the stack 1299abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai // of the crashing lwp. 1309abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai struct sigaltstack sig_stack; 1319abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai sig_stack.ss_sp = malloc(MINSIGSTKSZ); 1329abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai if (sig_stack.ss_sp == NULL) 1339abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai return; 1349abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai sig_stack.ss_size = MINSIGSTKSZ; 1359abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai sig_stack.ss_flags = 0; 1369abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 1379abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai if (sigaltstack(&sig_stack, NULL) < 0) 1389abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai return; 1399abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai for (size_t i = 0; i < sizeof(kSigTable) / sizeof(kSigTable[0]); ++i) 1409abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai SetupHandler(kSigTable[i]); 1419abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai} 1429abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 1439abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovaivoid ExceptionHandler::SetupHandler(int signo) { 1449abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai struct sigaction act, old_act; 1459abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai act.sa_handler = HandleException; 1469abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai act.sa_flags = SA_ONSTACK; 1479abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai if (sigaction(signo, &act, &old_act) < 0) 1489abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai return; 1499abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai old_handlers_[signo] = old_act.sa_handler; 1509abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai} 1519abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 1529abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovaivoid ExceptionHandler::TeardownHandler(int signo) { 1539abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai if (old_handlers_.find(signo) != old_handlers_.end()) { 1549abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai struct sigaction act; 1559abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai act.sa_handler = old_handlers_[signo]; 1569abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai act.sa_flags = 0; 1579abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai sigaction(signo, &act, 0); 1589abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai } 1599abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai} 1609abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 1619abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovaivoid ExceptionHandler::TeardownAllHandlers() { 1629abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai for (size_t i = 0; i < sizeof(kSigTable) / sizeof(kSigTable[0]); ++i) { 1639abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai TeardownHandler(kSigTable[i]); 1649abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai } 1659abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai} 1669abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 1679abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// static 1689abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovaivoid ExceptionHandler::HandleException(int signo) { 169dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek//void ExceptionHandler::HandleException(int signo, siginfo_t *sip, ucontext_t *sig_ctx) { 170dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek // The context information about the signal is put on the stack of 171dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek // the signal handler frame as value parameter. For some reasons, the 172dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek // prototype of the handler doesn't declare this information as parameter, we 173dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek // will do it by hand. The stack layout for a signal handler frame is here: 174dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek // http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libproc/common/Pstack.c#81 175dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek // 176dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek // However, if we are being called by another signal handler passing the 177dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek // signal up the chain, then we may not have this random extra parameter, 178dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek // so we may have to walk the stack to find it. We do the actual work 179dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek // on another thread, where it's a little safer, but we want the ebp 180dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek // from this frame to find it. 181dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek uintptr_t current_ebp = (uintptr_t)_getfp(); 182dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek 1839abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai pthread_mutex_lock(&handler_stack_mutex_); 1849abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai ExceptionHandler *current_handler = 1859abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai handler_stack_->at(handler_stack_->size() - ++handler_stack_index_); 1869abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai pthread_mutex_unlock(&handler_stack_mutex_); 1879abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 1889abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai // Restore original handler. 1899abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai current_handler->TeardownHandler(signo); 190dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek 191dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek ucontext_t *sig_ctx = NULL; 192dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek if (current_handler->InternalWriteMinidump(signo, current_ebp, &sig_ctx)) { 193dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// if (current_handler->InternalWriteMinidump(signo, &sig_ctx)) { 1949abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai // Fully handled this exception, safe to exit. 1959abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai exit(EXIT_FAILURE); 1969abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai } else { 1979abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai // Exception not fully handled, will call the next handler in stack to 1989abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai // process it. 1999abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai typedef void (*SignalHandler)(int signo); 2009abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai SignalHandler old_handler = 2019abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai reinterpret_cast<SignalHandler>(current_handler->old_handlers_[signo]); 2029abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai if (old_handler != NULL) 2039abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai old_handler(signo); 2049abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai } 2059abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 2069abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai pthread_mutex_lock(&handler_stack_mutex_); 2079abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai current_handler->SetupHandler(signo); 2089abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai --handler_stack_index_; 2099abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai // All the handlers in stack have been invoked to handle the exception, 2109abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai // normally the process should be terminated and should not reach here. 2119abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai // In case we got here, ask the OS to handle it to avoid endless loop, 2129abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai // normally the OS will generate a core and termiate the process. This 2139abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai // may be desired to debug the program. 2149abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai if (handler_stack_index_ == 0) 2159abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai signal(signo, SIG_DFL); 2169abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai pthread_mutex_unlock(&handler_stack_mutex_); 2179abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai} 2189abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 219dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekbool ExceptionHandler::InternalWriteMinidump(int signo, 220dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek uintptr_t sighandler_ebp, 221dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek ucontext_t **sig_ctx) { 2229abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai if (filter_ && !filter_(callback_context_)) 2239abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai return false; 2249abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 2259abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai bool success = false; 2269abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai GUID guid; 2279abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai char guid_str[kGUIDStringLength + 1]; 2289abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai if (CreateGUID(&guid) && GUIDToString(&guid, guid_str, sizeof(guid_str))) { 2299abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai char minidump_path[PATH_MAX]; 2309abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai snprintf(minidump_path, sizeof(minidump_path), "%s/%s.dmp", 2319abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai dump_path_c_, guid_str); 2329abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 2339abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai // Block all the signals we want to process when writing minidump. 2349abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai // We don't want it to be interrupted. 2359abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai sigset_t sig_blocked, sig_old; 2369abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai bool blocked = true; 2379abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai sigfillset(&sig_blocked); 2389abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai for (size_t i = 0; i < sizeof(kSigTable) / sizeof(kSigTable[0]); ++i) 2399abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai sigdelset(&sig_blocked, kSigTable[i]); 2409abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai if (sigprocmask(SIG_BLOCK, &sig_blocked, &sig_old) != 0) { 2419abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai blocked = false; 2429abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai print_message1(2, "HandleException: failed to block signals.\n"); 2439abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai } 2449abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 245dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek success = minidump_generator_.WriteMinidumpToFile( 246dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek minidump_path, signo, sighandler_ebp, sig_ctx); 2479abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 2489abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai // Unblock the signals. 2499abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai if (blocked) 2509abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai sigprocmask(SIG_SETMASK, &sig_old, &sig_old); 2519abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 2529abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai if (callback_) 2539abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai success = callback_(dump_path_c_, guid_str, callback_context_, success); 2549abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai } 2559abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai return success; 2569abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai} 2579abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai 2589abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai} // namespace google_breakpad 259