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"
14 #include "build/build_config.h"
18 const int kExceptionSignals
[] = {
19 SIGSEGV
, SIGABRT
, SIGFPE
, SIGILL
, SIGBUS
22 struct sigaction old_handlers
[arraysize(kExceptionSignals
)];
24 bool crash_handler_registered
;
26 std::string g_crash_msg
;
28 const char* g_crash_msg_ptr
; // Avoid invoking STL magic in a signal handler.
30 void AwExceptionHandler(int sig
, siginfo_t
* info
, void* uc
) {
31 if (g_crash_msg_ptr
!= NULL
)
32 __android_log_write(ANDROID_LOG_ERROR
, "chromium", g_crash_msg_ptr
);
34 // Detect if some buggy code in the embedder did reinstall the handler using
35 // signal() instead of sigaction() (which would cause |info| to be invalid).
36 struct sigaction cur_handler
;
37 if (sigaction(sig
, NULL
, &cur_handler
) != 0 ||
38 (cur_handler
.sa_flags
& SA_SIGINFO
) == 0) {
42 // We served our purpose. Now restore the old crash handlers. If the embedder
43 // did register a custom crash handler, it will be invoked by the kernel after
44 // this function returns. Otherwise, this will end up invoking the default
45 // signal disposition.
46 for (uint32_t i
= 0; i
< arraysize(kExceptionSignals
); ++i
) {
47 if (sigaction(kExceptionSignals
[i
], &old_handlers
[i
], NULL
) == -1) {
48 signal(kExceptionSignals
[i
], SIG_DFL
);
52 if ((info
!= NULL
&& info
->si_pid
) || sig
== SIGABRT
) {
53 // This signal was triggered by somebody sending us the signal with kill().
54 // In order to retrigger it, we have to queue a new signal by calling
55 // kill() ourselves. The special case (si_pid == 0 && sig == SIGABRT) is
56 // due to the kernel sending a SIGABRT from a user request via SysRQ.
57 if (syscall(__NR_tgkill
, getpid(), syscall(__NR_gettid
), sig
) < 0) {
58 // If we failed to kill ourselves resort to terminating uncleanly.
66 namespace android_webview
{
67 namespace crash_handler
{
69 void RegisterCrashHandler(const std::string
& version
) {
70 #if defined(ARCH_CPU_X86_FAMILY)
71 // Don't install signal handler on X86/64 because this breaks binary
72 // translators that handle SIGSEGV in userspace and get chained after our
73 // handler. See crbug.com/477444
77 if (crash_handler_registered
) {
82 g_crash_msg
= "### WebView " + version
;
83 g_crash_msg_ptr
= g_crash_msg
.c_str();
85 // Fail if unable to store all the old handlers.
86 for (uint32_t i
= 0; i
< arraysize(kExceptionSignals
); ++i
) {
87 if (sigaction(kExceptionSignals
[i
], NULL
, &old_handlers
[i
]) == -1) {
88 LOG(ERROR
) << "Error while trying to retrieve old handler for signal "
89 << kExceptionSignals
[i
] << ")";
95 memset(&sa
, 0, sizeof(sa
));
96 sigemptyset(&sa
.sa_mask
);
98 // Mask all exception signals when we're handling one of them.
99 for (uint32_t i
= 0; i
< arraysize(kExceptionSignals
); ++i
)
100 sigaddset(&sa
.sa_mask
, kExceptionSignals
[i
]);
102 sa
.sa_sigaction
= AwExceptionHandler
;
103 sa
.sa_flags
= SA_ONSTACK
| SA_SIGINFO
;
105 for (uint32_t i
= 0; i
< arraysize(kExceptionSignals
); ++i
) {
106 if (sigaction(kExceptionSignals
[i
], &sa
, NULL
) == -1) {
107 // At this point it is impractical to back out changes, and so failure to
108 // install a signal is intentionally ignored.
109 LOG(ERROR
) << "Error while overriding handler for signal "
110 << kExceptionSignals
[i
];
114 crash_handler_registered
= true;
117 } // namespace crash_handler
118 } // namespace android_webview