summaryrefslogtreecommitdiffstats
path: root/android_webview/common
diff options
context:
space:
mode:
authorprimiano <primiano@chromium.org>2014-12-01 04:52:42 -0800
committerCommit bot <commit-bot@chromium.org>2014-12-01 12:52:55 +0000
commit502567f2f5ee10f98a62d1f399628468c5d4388b (patch)
treee8270079bed296e94288597af75be40a2affb1e2 /android_webview/common
parentbbb9c85bbcff205711e96ee6273f7c6fcd4db449 (diff)
downloadchromium_src-502567f2f5ee10f98a62d1f399628468c5d4388b.zip
chromium_src-502567f2f5ee10f98a62d1f399628468c5d4388b.tar.gz
chromium_src-502567f2f5ee10f98a62d1f399628468c5d4388b.tar.bz2
[android] Fix SIGABRT handling in the WebView crash handler.
The WebView fingerprint crash handler introduced in crrev.com/678763005 was failing to cover the case of signals delivered through kill/raise. Conversely to what happens with segfaults, where the kernel keeps invoking the registered SIGSEGV handler, in these other cases the signal needs to be re-enqueued before chaining to the next handler. This is the case of abort(), which internally does a raise(SIGABRT). BUG=437788 Review URL: https://codereview.chromium.org/769843002 Cr-Commit-Position: refs/heads/master@{#306179}
Diffstat (limited to 'android_webview/common')
-rw-r--r--android_webview/common/aw_crash_handler.cc23
1 files changed, 23 insertions, 0 deletions
diff --git a/android_webview/common/aw_crash_handler.cc b/android_webview/common/aw_crash_handler.cc
index a637298..fbd4285 100644
--- a/android_webview/common/aw_crash_handler.cc
+++ b/android_webview/common/aw_crash_handler.cc
@@ -6,6 +6,9 @@
#include <android/log.h>
#include <signal.h>
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+#include <unistd.h>
#include "base/logging.h"
@@ -27,6 +30,14 @@ void AwExceptionHandler(int sig, siginfo_t* info, void* uc) {
if (g_crash_msg_ptr != NULL)
__android_log_write(ANDROID_LOG_ERROR, "chromium", g_crash_msg_ptr);
+ // Detect if some buggy code in the embedder did reinstall the handler using
+ // signal() instead of sigaction() (which would cause |info| to be invalid).
+ struct sigaction cur_handler;
+ if (sigaction(sig, NULL, &cur_handler) != 0 ||
+ (cur_handler.sa_flags & SA_SIGINFO) == 0) {
+ info = NULL;
+ }
+
// We served our purpose. Now restore the old crash handlers. If the embedder
// did register a custom crash handler, it will be invoked by the kernel after
// this function returns. Otherwise, this will end up invoking the default
@@ -36,6 +47,17 @@ void AwExceptionHandler(int sig, siginfo_t* info, void* uc) {
signal(kExceptionSignals[i], SIG_DFL);
}
}
+
+ if ((info != NULL && info->si_pid) || sig == SIGABRT) {
+ // This signal was triggered by somebody sending us the signal with kill().
+ // In order to retrigger it, we have to queue a new signal by calling
+ // kill() ourselves. The special case (si_pid == 0 && sig == SIGABRT) is
+ // due to the kernel sending a SIGABRT from a user request via SysRQ.
+ if (syscall(__NR_tgkill, getpid(), syscall(__NR_gettid), sig) < 0) {
+ // If we failed to kill ourselves resort to terminating uncleanly.
+ exit(1);
+ }
+ }
}
} // namespace
@@ -65,6 +87,7 @@ void RegisterCrashHandler(const std::string& version) {
memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
+ // Mask all exception signals when we're handling one of them.
for (uint32_t i = 0; i < arraysize(kExceptionSignals); ++i)
sigaddset(&sa.sa_mask, kExceptionSignals[i]);