summaryrefslogtreecommitdiffstats
path: root/toolkit/crashreporter/google-breakpad/src/client/solaris/handler/exception_handler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/crashreporter/google-breakpad/src/client/solaris/handler/exception_handler.cc')
-rw-r--r--toolkit/crashreporter/google-breakpad/src/client/solaris/handler/exception_handler.cc258
1 files changed, 0 insertions, 258 deletions
diff --git a/toolkit/crashreporter/google-breakpad/src/client/solaris/handler/exception_handler.cc b/toolkit/crashreporter/google-breakpad/src/client/solaris/handler/exception_handler.cc
deleted file mode 100644
index 7fc8d2557..000000000
--- a/toolkit/crashreporter/google-breakpad/src/client/solaris/handler/exception_handler.cc
+++ /dev/null
@@ -1,258 +0,0 @@
-// Copyright (c) 2007, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: Alfred Peng
-
-#include <signal.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <cassert>
-#include <cstdlib>
-#include <ctime>
-
-#include "client/solaris/handler/exception_handler.h"
-#include "common/solaris/guid_creator.h"
-#include "common/solaris/message_output.h"
-#include "google_breakpad/common/minidump_format.h"
-
-namespace google_breakpad {
-
-// Signals that we are interested.
-static const int kSigTable[] = {
- SIGSEGV,
- SIGABRT,
- SIGFPE,
- SIGILL,
- SIGBUS
-};
-
-std::vector<ExceptionHandler*> *ExceptionHandler::handler_stack_ = NULL;
-int ExceptionHandler::handler_stack_index_ = 0;
-pthread_mutex_t ExceptionHandler::handler_stack_mutex_ =
- PTHREAD_MUTEX_INITIALIZER;
-
-ExceptionHandler::ExceptionHandler(const string &dump_path,
- FilterCallback filter,
- MinidumpCallback callback,
- void *callback_context,
- bool install_handler)
- : filter_(filter),
- callback_(callback),
- callback_context_(callback_context),
- dump_path_(),
- installed_handler_(install_handler) {
- set_dump_path(dump_path);
-
- if (install_handler) {
- SetupHandler();
- }
-
- if (install_handler) {
- pthread_mutex_lock(&handler_stack_mutex_);
-
- if (handler_stack_ == NULL)
- handler_stack_ = new std::vector<ExceptionHandler *>;
- handler_stack_->push_back(this);
- pthread_mutex_unlock(&handler_stack_mutex_);
- }
-}
-
-ExceptionHandler::~ExceptionHandler() {
- TeardownAllHandlers();
- pthread_mutex_lock(&handler_stack_mutex_);
- if (handler_stack_->back() == this) {
- handler_stack_->pop_back();
- } else {
- print_message1(2, "warning: removing Breakpad handler out of order\n");
- for (std::vector<ExceptionHandler *>::iterator iterator =
- handler_stack_->begin();
- iterator != handler_stack_->end();
- ++iterator) {
- if (*iterator == this) {
- handler_stack_->erase(iterator);
- }
- }
- }
-
- if (handler_stack_->empty()) {
- // When destroying the last ExceptionHandler that installed a handler,
- // clean up the handler stack.
- delete handler_stack_;
- handler_stack_ = NULL;
- }
- pthread_mutex_unlock(&handler_stack_mutex_);
-}
-
-bool ExceptionHandler::WriteMinidump() {
- return InternalWriteMinidump(0, 0, NULL);
-}
-
-// static
-bool ExceptionHandler::WriteMinidump(const string &dump_path,
- MinidumpCallback callback,
- void *callback_context) {
- ExceptionHandler handler(dump_path, NULL, callback,
- callback_context, false);
- return handler.InternalWriteMinidump(0, 0, NULL);
-}
-
-void ExceptionHandler::SetupHandler() {
- // Signal on a different stack to avoid using the stack
- // of the crashing lwp.
- struct sigaltstack sig_stack;
- sig_stack.ss_sp = malloc(MINSIGSTKSZ);
- if (sig_stack.ss_sp == NULL)
- return;
- sig_stack.ss_size = MINSIGSTKSZ;
- sig_stack.ss_flags = 0;
-
- if (sigaltstack(&sig_stack, NULL) < 0)
- return;
- for (size_t i = 0; i < sizeof(kSigTable) / sizeof(kSigTable[0]); ++i)
- SetupHandler(kSigTable[i]);
-}
-
-void ExceptionHandler::SetupHandler(int signo) {
- struct sigaction act, old_act;
- act.sa_handler = HandleException;
- act.sa_flags = SA_ONSTACK;
- if (sigaction(signo, &act, &old_act) < 0)
- return;
- old_handlers_[signo] = old_act.sa_handler;
-}
-
-void ExceptionHandler::TeardownHandler(int signo) {
- if (old_handlers_.find(signo) != old_handlers_.end()) {
- struct sigaction act;
- act.sa_handler = old_handlers_[signo];
- act.sa_flags = 0;
- sigaction(signo, &act, 0);
- }
-}
-
-void ExceptionHandler::TeardownAllHandlers() {
- for (size_t i = 0; i < sizeof(kSigTable) / sizeof(kSigTable[0]); ++i) {
- TeardownHandler(kSigTable[i]);
- }
-}
-
-// static
-void ExceptionHandler::HandleException(int signo) {
-//void ExceptionHandler::HandleException(int signo, siginfo_t *sip, ucontext_t *sig_ctx) {
- // The context information about the signal is put on the stack of
- // the signal handler frame as value parameter. For some reasons, the
- // prototype of the handler doesn't declare this information as parameter, we
- // will do it by hand. The stack layout for a signal handler frame is here:
- // http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libproc/common/Pstack.c#81
- //
- // However, if we are being called by another signal handler passing the
- // signal up the chain, then we may not have this random extra parameter,
- // so we may have to walk the stack to find it. We do the actual work
- // on another thread, where it's a little safer, but we want the ebp
- // from this frame to find it.
- uintptr_t current_ebp = (uintptr_t)_getfp();
-
- pthread_mutex_lock(&handler_stack_mutex_);
- ExceptionHandler *current_handler =
- handler_stack_->at(handler_stack_->size() - ++handler_stack_index_);
- pthread_mutex_unlock(&handler_stack_mutex_);
-
- // Restore original handler.
- current_handler->TeardownHandler(signo);
-
- ucontext_t *sig_ctx = NULL;
- if (current_handler->InternalWriteMinidump(signo, current_ebp, &sig_ctx)) {
-// if (current_handler->InternalWriteMinidump(signo, &sig_ctx)) {
- // Fully handled this exception, safe to exit.
- exit(EXIT_FAILURE);
- } else {
- // Exception not fully handled, will call the next handler in stack to
- // process it.
- typedef void (*SignalHandler)(int signo);
- SignalHandler old_handler =
- reinterpret_cast<SignalHandler>(current_handler->old_handlers_[signo]);
- if (old_handler != NULL)
- old_handler(signo);
- }
-
- pthread_mutex_lock(&handler_stack_mutex_);
- current_handler->SetupHandler(signo);
- --handler_stack_index_;
- // All the handlers in stack have been invoked to handle the exception,
- // normally the process should be terminated and should not reach here.
- // In case we got here, ask the OS to handle it to avoid endless loop,
- // normally the OS will generate a core and termiate the process. This
- // may be desired to debug the program.
- if (handler_stack_index_ == 0)
- signal(signo, SIG_DFL);
- pthread_mutex_unlock(&handler_stack_mutex_);
-}
-
-bool ExceptionHandler::InternalWriteMinidump(int signo,
- uintptr_t sighandler_ebp,
- ucontext_t **sig_ctx) {
- if (filter_ && !filter_(callback_context_))
- return false;
-
- bool success = false;
- GUID guid;
- char guid_str[kGUIDStringLength + 1];
- if (CreateGUID(&guid) && GUIDToString(&guid, guid_str, sizeof(guid_str))) {
- char minidump_path[PATH_MAX];
- snprintf(minidump_path, sizeof(minidump_path), "%s/%s.dmp",
- dump_path_c_, guid_str);
-
- // Block all the signals we want to process when writing minidump.
- // We don't want it to be interrupted.
- sigset_t sig_blocked, sig_old;
- bool blocked = true;
- sigfillset(&sig_blocked);
- for (size_t i = 0; i < sizeof(kSigTable) / sizeof(kSigTable[0]); ++i)
- sigdelset(&sig_blocked, kSigTable[i]);
- if (sigprocmask(SIG_BLOCK, &sig_blocked, &sig_old) != 0) {
- blocked = false;
- print_message1(2, "HandleException: failed to block signals.\n");
- }
-
- success = minidump_generator_.WriteMinidumpToFile(
- minidump_path, signo, sighandler_ebp, sig_ctx);
-
- // Unblock the signals.
- if (blocked)
- sigprocmask(SIG_SETMASK, &sig_old, &sig_old);
-
- if (callback_)
- success = callback_(dump_path_c_, guid_str, callback_context_, success);
- }
- return success;
-}
-
-} // namespace google_breakpad