Re-land: C++ readability review
[chromium-blink-merge.git] / android_webview / common / aw_crash_handler.cc
blob7dcdc9d5533fa816ed21694f40d7cc08f380960f
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "android_webview/common/aw_crash_handler.h"
7 #include <android/log.h>
8 #include <signal.h>
9 #include <sys/prctl.h>
10 #include <sys/syscall.h>
11 #include <unistd.h>
13 #include "base/logging.h"
15 namespace {
17 const int kExceptionSignals[] = {
18 SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS
21 struct sigaction old_handlers[arraysize(kExceptionSignals)];
23 bool crash_handler_registered;
25 std::string g_crash_msg;
27 const char* g_crash_msg_ptr; // Avoid invoking STL magic in a signal handler.
29 void AwExceptionHandler(int sig, siginfo_t* info, void* uc) {
30 if (g_crash_msg_ptr != NULL)
31 __android_log_write(ANDROID_LOG_ERROR, "chromium", g_crash_msg_ptr);
33 // Detect if some buggy code in the embedder did reinstall the handler using
34 // signal() instead of sigaction() (which would cause |info| to be invalid).
35 struct sigaction cur_handler;
36 if (sigaction(sig, NULL, &cur_handler) != 0 ||
37 (cur_handler.sa_flags & SA_SIGINFO) == 0) {
38 info = NULL;
41 // We served our purpose. Now restore the old crash handlers. If the embedder
42 // did register a custom crash handler, it will be invoked by the kernel after
43 // this function returns. Otherwise, this will end up invoking the default
44 // signal disposition.
45 for (uint32_t i = 0; i < arraysize(kExceptionSignals); ++i) {
46 if (sigaction(kExceptionSignals[i], &old_handlers[i], NULL) == -1) {
47 signal(kExceptionSignals[i], SIG_DFL);
51 if ((info != NULL && info->si_pid) || sig == SIGABRT) {
52 // This signal was triggered by somebody sending us the signal with kill().
53 // In order to retrigger it, we have to queue a new signal by calling
54 // kill() ourselves. The special case (si_pid == 0 && sig == SIGABRT) is
55 // due to the kernel sending a SIGABRT from a user request via SysRQ.
56 if (syscall(__NR_tgkill, getpid(), syscall(__NR_gettid), sig) < 0) {
57 // If we failed to kill ourselves resort to terminating uncleanly.
58 exit(1);
63 } // namespace
65 namespace android_webview {
66 namespace crash_handler {
68 void RegisterCrashHandler(const std::string& version) {
69 if (crash_handler_registered) {
70 NOTREACHED();
71 return;
74 g_crash_msg = "### WebView " + version;
75 g_crash_msg_ptr = g_crash_msg.c_str();
77 // Fail if unable to store all the old handlers.
78 for (uint32_t i = 0; i < arraysize(kExceptionSignals); ++i) {
79 if (sigaction(kExceptionSignals[i], NULL, &old_handlers[i]) == -1) {
80 LOG(ERROR) << "Error while trying to retrieve old handler for signal "
81 << kExceptionSignals[i] << ")";
82 return;
86 struct sigaction sa;
87 memset(&sa, 0, sizeof(sa));
88 sigemptyset(&sa.sa_mask);
90 // Mask all exception signals when we're handling one of them.
91 for (uint32_t i = 0; i < arraysize(kExceptionSignals); ++i)
92 sigaddset(&sa.sa_mask, kExceptionSignals[i]);
94 sa.sa_sigaction = AwExceptionHandler;
95 sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
97 for (uint32_t i = 0; i < arraysize(kExceptionSignals); ++i) {
98 if (sigaction(kExceptionSignals[i], &sa, NULL) == -1) {
99 // At this point it is impractical to back out changes, and so failure to
100 // install a signal is intentionally ignored.
101 LOG(ERROR) << "Error while overriding handler for signal "
102 << kExceptionSignals[i];
106 crash_handler_registered = true;
109 } // namespace crash_handler
110 } // namespace android_webview