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>
10 #include <sys/syscall.h>
13 #include "base/logging.h"
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) {
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.
65 namespace android_webview
{
66 namespace crash_handler
{
68 void RegisterCrashHandler(const std::string
& version
) {
69 if (crash_handler_registered
) {
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
] << ")";
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