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