aboutsummaryrefslogtreecommitdiff
path: root/src/client/linux/handler
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/linux/handler')
-rw-r--r--src/client/linux/handler/exception_handler.cc44
-rw-r--r--src/client/linux/handler/exception_handler.h6
-rw-r--r--src/client/linux/handler/exception_handler_unittest.cc11
3 files changed, 42 insertions, 19 deletions
diff --git a/src/client/linux/handler/exception_handler.cc b/src/client/linux/handler/exception_handler.cc
index 01081878..038612f2 100644
--- a/src/client/linux/handler/exception_handler.cc
+++ b/src/client/linux/handler/exception_handler.cc
@@ -80,6 +80,9 @@
#include <ucontext.h>
#include <unistd.h>
+#include <algorithm>
+#include <vector>
+
#include "common/linux/linux_libc_support.h"
#include "common/linux/linux_syscall_support.h"
#include "common/linux/memory.h"
@@ -88,7 +91,7 @@
// A wrapper for the tgkill syscall: send a signal to a specific thread.
static int tgkill(pid_t tgid, pid_t tid, int sig) {
- syscall(__NR_tgkill, tgid, tid, sig);
+ return syscall(__NR_tgkill, tgid, tid, sig);
return 0;
}
@@ -145,7 +148,6 @@ void ExceptionHandler::Init(const std::string &dump_path,
const int server_fd)
{
crash_handler_ = NULL;
-
if (0 <= server_fd)
crash_generation_client_
.reset(CrashGenerationClient::TryCreate(server_fd));
@@ -209,7 +211,11 @@ void ExceptionHandler::UninstallHandlers() {
sigaction(old_handlers_[i].first, action, NULL);
delete action;
}
-
+ pthread_mutex_lock(&handler_stack_mutex_);
+ std::vector<ExceptionHandler*>::iterator handler =
+ std::find(handler_stack_->begin(), handler_stack_->end(), this);
+ handler_stack_->erase(handler);
+ pthread_mutex_unlock(&handler_stack_mutex_);
old_handlers_.clear();
}
@@ -231,12 +237,15 @@ void ExceptionHandler::UpdateNextID() {
}
}
+// void ExceptionHandler::set_crash_handler(HandlerCallback callback) {
+// crash_handler_ = callback;
+// }
+
// This function runs in a compromised context: see the top of the file.
// Runs on the crashing thread.
// 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_);
if (!handler_stack_->size()) {
@@ -288,18 +297,25 @@ bool ExceptionHandler::HandleSignal(int sig, siginfo_t* info, void* uc) {
// Allow ourselves to be dumped.
sys_prctl(PR_SET_DUMPABLE, 1);
-
CrashContext context;
memcpy(&context.siginfo, info, sizeof(siginfo_t));
memcpy(&context.context, uc, sizeof(struct ucontext));
- memcpy(&context.float_state, ((struct ucontext *)uc)->uc_mcontext.fpregs,
- sizeof(context.float_state));
+#if !defined(__ARM_EABI__)
+ // FP state is not part of user ABI on ARM Linux.
+ struct ucontext *uc_ptr = (struct ucontext*)uc;
+ if (uc_ptr->uc_mcontext.fpregs) {
+ memcpy(&context.float_state,
+ uc_ptr->uc_mcontext.fpregs,
+ sizeof(context.float_state));
+ }
+#endif
context.tid = sys_gettid();
-
- if (crash_handler_ && crash_handler_(&context, sizeof(context),
- callback_context_))
- return true;
-
+ if (crash_handler_ != NULL) {
+ if (crash_handler_(&context, sizeof(context),
+ callback_context_)) {
+ return true;
+ }
+ }
return GenerateDump(&context);
}
@@ -364,6 +380,7 @@ bool ExceptionHandler::WriteMinidump(const std::string &dump_path,
}
bool ExceptionHandler::WriteMinidump() {
+#if !defined(__ARM_EABI__)
// Allow ourselves to be dumped.
sys_prctl(PR_SET_DUMPABLE, 1);
@@ -378,6 +395,9 @@ bool ExceptionHandler::WriteMinidump() {
bool success = GenerateDump(&context);
UpdateNextID();
return success;
+#else
+ return false;
+#endif // !defined(__ARM_EABI__)
}
} // namespace google_breakpad
diff --git a/src/client/linux/handler/exception_handler.h b/src/client/linux/handler/exception_handler.h
index 6182a6c1..2a497037 100644
--- a/src/client/linux/handler/exception_handler.h
+++ b/src/client/linux/handler/exception_handler.h
@@ -34,6 +34,7 @@
#include <string>
#include <signal.h>
+#include <stdio.h>
#include "client/linux/crash_generation/crash_generation_client.h"
#include "processor/scoped_ptr.h"
@@ -42,6 +43,8 @@ struct sigaction;
namespace google_breakpad {
+class ExceptionHandler;
+
// ExceptionHandler
//
// ExceptionHandler can write a minidump file when an exception occurs,
@@ -163,7 +166,10 @@ class ExceptionHandler {
siginfo_t siginfo;
pid_t tid; // the crashing thread.
struct ucontext context;
+#if !defined(__ARM_EABI__)
+ // #ifdef this out because FP state is not part of user ABI for Linux ARM.
struct _libc_fpstate float_state;
+#endif
};
// Returns whether out-of-process dump generation is used or not.
diff --git a/src/client/linux/handler/exception_handler_unittest.cc b/src/client/linux/handler/exception_handler_unittest.cc
index 2e8a6dbe..9747fe71 100644
--- a/src/client/linux/handler/exception_handler_unittest.cc
+++ b/src/client/linux/handler/exception_handler_unittest.cc
@@ -36,7 +36,7 @@
#include <sys/socket.h>
#include <sys/uio.h>
-#include "client/linux/handler//exception_handler.h"
+#include "client/linux/handler/exception_handler.h"
#include "client/linux/minidump_writer/minidump_writer.h"
#include "common/linux/eintr_wrapper.h"
#include "common/linux/linux_libc_support.h"
@@ -112,8 +112,8 @@ TEST(ExceptionHandlerTest, ChildCrash) {
ASSERT_TRUE(pfd.revents & POLLIN);
uint32_t len;
- ASSERT_EQ(read(fds[0], &len, sizeof(len)), sizeof(len));
- ASSERT_LT(len, 2048);
+ ASSERT_EQ(read(fds[0], &len, sizeof(len)), (ssize_t)sizeof(len));
+ ASSERT_LT(len, (uint32_t)2048);
char* filename = reinterpret_cast<char*>(malloc(len + 1));
ASSERT_EQ(read(fds[0], filename, len), len);
filename[len] = 0;
@@ -137,12 +137,10 @@ CrashHandler(const void* crash_context, size_t crash_context_size,
const int fd = (intptr_t) context;
int fds[2];
pipe(fds);
-
struct kernel_msghdr msg = {0};
struct kernel_iovec iov;
iov.iov_base = const_cast<void*>(crash_context);
iov.iov_len = crash_context_size;
-
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
char cmsg[kControlMsgSize];
@@ -183,11 +181,10 @@ TEST(ExceptionHandlerTest, ExternalDumper) {
const pid_t child = fork();
if (child == 0) {
close(fds[0]);
- ExceptionHandler handler("/tmp", NULL, NULL, (void*) fds[1], true);
+ ExceptionHandler handler("/tmp1", NULL, NULL, (void*) fds[1], true);
handler.set_crash_handler(CrashHandler);
*reinterpret_cast<int*>(NULL) = 0;
}
-
close(fds[1]);
struct msghdr msg = {0};
struct iovec iov;