diff options
Diffstat (limited to 'android_webview/common')
-rw-r--r-- | android_webview/common/aw_crash_handler.cc | 87 | ||||
-rw-r--r-- | android_webview/common/aw_crash_handler.h | 18 |
2 files changed, 105 insertions, 0 deletions
diff --git a/android_webview/common/aw_crash_handler.cc b/android_webview/common/aw_crash_handler.cc new file mode 100644 index 0000000..a637298 --- /dev/null +++ b/android_webview/common/aw_crash_handler.cc @@ -0,0 +1,87 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "android_webview/common/aw_crash_handler.h" + +#include <android/log.h> +#include <signal.h> + +#include "base/logging.h" + +namespace { + +const int kExceptionSignals[] = { + SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS +}; + +struct sigaction old_handlers[arraysize(kExceptionSignals)]; + +bool crash_handler_registered; + +std::string g_crash_msg; + +const char* g_crash_msg_ptr; // Avoid invoking STL magic in a signal handler. + +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); + + // 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 + // signal disposition. + for (uint32_t i = 0; i < arraysize(kExceptionSignals); ++i) { + if (sigaction(kExceptionSignals[i], &old_handlers[i], NULL) == -1) { + signal(kExceptionSignals[i], SIG_DFL); + } + } +} + +} // namespace + +namespace android_webview { +namespace crash_handler { + +void RegisterCrashHandler(const std::string& version) { + if (crash_handler_registered) { + NOTREACHED(); + return; + } + + g_crash_msg = "### WebView crash. " + version; + g_crash_msg_ptr = g_crash_msg.c_str(); + + // Fail if unable to store all the old handlers. + for (uint32_t i = 0; i < arraysize(kExceptionSignals); ++i) { + if (sigaction(kExceptionSignals[i], NULL, &old_handlers[i]) == -1) { + LOG(ERROR) << "Error while trying to retrieve old handler for signal " + << kExceptionSignals[i] << ")"; + return; + } + } + + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sigemptyset(&sa.sa_mask); + + for (uint32_t i = 0; i < arraysize(kExceptionSignals); ++i) + sigaddset(&sa.sa_mask, kExceptionSignals[i]); + + sa.sa_sigaction = AwExceptionHandler; + sa.sa_flags = SA_ONSTACK | SA_SIGINFO; + + for (uint32_t i = 0; i < arraysize(kExceptionSignals); ++i) { + if (sigaction(kExceptionSignals[i], &sa, NULL) == -1) { + // At this point it is impractical to back out changes, and so failure to + // install a signal is intentionally ignored. + LOG(ERROR) << "Error while overriding handler for signal " + << kExceptionSignals[i]; + } + } + + crash_handler_registered = true; +} + +} // namespace crash_handler +} // namespace android_webview diff --git a/android_webview/common/aw_crash_handler.h b/android_webview/common/aw_crash_handler.h new file mode 100644 index 0000000..60e1d15 --- /dev/null +++ b/android_webview/common/aw_crash_handler.h @@ -0,0 +1,18 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ANDROID_WEBVIEW_COMMON_AW_CRASH_HANDLER_H_ +#define ANDROID_WEBVIEW_COMMON_AW_CRASH_HANDLER_H_ + +#include <string> + +namespace android_webview { +namespace crash_handler { + +void RegisterCrashHandler(const std::string& version); + +} // namespace crash_handler +} // namespace android_webview + +#endif // ANDROID_WEBVIEW_COMMON_AW_CRASH_HANDLER_H_ |