#include <errno.h>
#include <fcntl.h>
#include <linux/limits.h>
+#include <pthread.h>
#include <sched.h>
#include <signal.h>
#include <stdio.h>
// one is too small.
if (sys_sigaltstack(NULL, &old_stack) == -1 || !old_stack.ss_sp ||
old_stack.ss_size < kSigStackSize) {
- new_stack.ss_sp = malloc(kSigStackSize);
+ new_stack.ss_sp = calloc(1, kSigStackSize);
new_stack.ss_size = kSigStackSize;
if (sys_sigaltstack(&new_stack, NULL) == -1) {
stack_installed = false;
}
-} // namespace
+// The global exception handler stack. This is needed because there may exist
+// multiple ExceptionHandler instances in a process. Each will have itself
+// registered in this stack.
+std::vector<ExceptionHandler*>* g_handler_stack_ = NULL;
+pthread_mutex_t g_handler_stack_mutex_ = PTHREAD_MUTEX_INITIALIZER;
-// We can stack multiple exception handlers. In that case, this is the global
-// which holds the stack.
-std::vector<ExceptionHandler*>* ExceptionHandler::handler_stack_ = NULL;
-pthread_mutex_t ExceptionHandler::handler_stack_mutex_ =
- PTHREAD_MUTEX_INITIALIZER;
+} // namespace
// Runs before crashing: normal context.
ExceptionHandler::ExceptionHandler(const MinidumpDescriptor& descriptor,
if (!IsOutOfProcess() && !minidump_descriptor_.IsFD())
minidump_descriptor_.UpdatePath();
- pthread_mutex_lock(&handler_stack_mutex_);
- if (!handler_stack_)
- handler_stack_ = new std::vector<ExceptionHandler*>;
+ pthread_mutex_lock(&g_handler_stack_mutex_);
+ if (!g_handler_stack_)
+ g_handler_stack_ = new std::vector<ExceptionHandler*>;
if (install_handler) {
InstallAlternateStackLocked();
InstallHandlersLocked();
}
- handler_stack_->push_back(this);
- pthread_mutex_unlock(&handler_stack_mutex_);
+ g_handler_stack_->push_back(this);
+ pthread_mutex_unlock(&g_handler_stack_mutex_);
}
// Runs before crashing: normal context.
ExceptionHandler::~ExceptionHandler() {
- pthread_mutex_lock(&handler_stack_mutex_);
+ pthread_mutex_lock(&g_handler_stack_mutex_);
std::vector<ExceptionHandler*>::iterator handler =
- std::find(handler_stack_->begin(), handler_stack_->end(), this);
- handler_stack_->erase(handler);
- if (handler_stack_->empty()) {
- delete handler_stack_;
- handler_stack_ = NULL;
+ std::find(g_handler_stack_->begin(), g_handler_stack_->end(), this);
+ g_handler_stack_->erase(handler);
+ if (g_handler_stack_->empty()) {
+ delete g_handler_stack_;
+ g_handler_stack_ = NULL;
RestoreAlternateStackLocked();
RestoreHandlersLocked();
}
- pthread_mutex_unlock(&handler_stack_mutex_);
+ pthread_mutex_unlock(&g_handler_stack_mutex_);
}
// Runs before crashing: normal context.
// static
void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
// All the exception signals are blocked at this point.
- pthread_mutex_lock(&handler_stack_mutex_);
+ pthread_mutex_lock(&g_handler_stack_mutex_);
// Sometimes, Breakpad runs inside a process where some other buggy code
// saves and restores signal handlers temporarily with 'signal'
// default one to avoid an infinite loop here.
signal(sig, SIG_DFL);
}
- pthread_mutex_unlock(&handler_stack_mutex_);
+ pthread_mutex_unlock(&g_handler_stack_mutex_);
return;
}
bool handled = false;
- for (int i = handler_stack_->size() - 1; !handled && i >= 0; --i) {
- handled = (*handler_stack_)[i]->HandleSignal(sig, info, uc);
+ for (int i = g_handler_stack_->size() - 1; !handled && i >= 0; --i) {
+ handled = (*g_handler_stack_)[i]->HandleSignal(sig, info, uc);
}
// Upon returning from this signal handler, sig will become unmasked and then
RestoreHandlersLocked();
}
- pthread_mutex_unlock(&handler_stack_mutex_);
+ pthread_mutex_unlock(&g_handler_stack_mutex_);
if (info->si_pid || sig == SIGABRT) {
// This signal was triggered by somebody sending us the signal with kill().
sys_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
}
CrashContext context;
+ // Fill in all the holes in the struct to make Valgrind happy.
+ memset(&context, 0, sizeof(context));
memcpy(&context.siginfo, info, sizeof(siginfo_t));
memcpy(&context.context, uc, sizeof(struct ucontext));
#if defined(__aarch64__)
// of caution than smash it into random locations.
static const unsigned kChildStackSize = 16000;
PageAllocator allocator;
- uint8_t* stack = (uint8_t*) allocator.Alloc(kChildStackSize);
+ uint8_t* stack = reinterpret_cast<uint8_t*>(allocator.Alloc(kChildStackSize));
if (!stack)
return false;
// clone() needs the top-most address. (scrub just to be safe)