aboutsummaryrefslogtreecommitdiff
path: root/src/client/linux/handler
diff options
context:
space:
mode:
authormark@chromium.org <mark@chromium.org>2015-04-10 17:57:24 +0000
committermark@chromium.org <mark@chromium.org>2015-04-10 17:57:24 +0000
commitcfdf7cf8a97fbd5651ce0c22735b8a26904749e6 (patch)
tree2bc74b7c8b7073cbd9574b9bb20cc24531cde383 /src/client/linux/handler
parentFix compilation with gcc --std=c++11 (diff)
downloadbreakpad-cfdf7cf8a97fbd5651ce0c22735b8a26904749e6.tar.xz
Workaround Android sigaction bug
On Android L+, signal and sigaction symbols are provided by libsigchain that override the system's versions. There is a bug in these functions where they essentially ignore requests to install SIG_DFL. Workaround this issue by explicitly performing a syscall to __NR_rt_sigaction to install SIG_DFL on Android. BUG=473973 Patch by Chris Hopman <cjhopman@chromium.org> Review URL: https://breakpad.appspot.com/1804002/ git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1438 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/client/linux/handler')
-rw-r--r--src/client/linux/handler/exception_handler.cc24
1 files changed, 21 insertions, 3 deletions
diff --git a/src/client/linux/handler/exception_handler.cc b/src/client/linux/handler/exception_handler.cc
index 3e2d1962..2ee7e4c3 100644
--- a/src/client/linux/handler/exception_handler.cc
+++ b/src/client/linux/handler/exception_handler.cc
@@ -188,6 +188,24 @@ void RestoreAlternateStackLocked() {
stack_installed = false;
}
+void InstallDefaultHandler(int sig) {
+#if defined(__ANDROID__)
+ // Android L+ expose signal and sigaction symbols that override the system
+ // ones. There is a bug in these functions where a request to set the handler
+ // to SIG_DFL is ignored. In that case, an infinite loop is entered as the
+ // signal is repeatedly sent to breakpad's signal handler.
+ // To work around this, directly call the system's sigaction.
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = SIG_DFL;
+ sa.sa_flags = SA_RESTART;
+ syscall(__NR_sigaction, sig, &sa, NULL);
+#else
+ signal(sig, SIG_DFL);
+#endif
+}
+
// The global exception handler stack. This is needed because there may exist
// multiple ExceptionHandler instances in a process. Each will have itself
// registered in this stack.
@@ -283,7 +301,7 @@ void ExceptionHandler::RestoreHandlersLocked() {
for (int i = 0; i < kNumHandledSignals; ++i) {
if (sigaction(kExceptionSignals[i], &old_handlers[i], NULL) == -1) {
- signal(kExceptionSignals[i], SIG_DFL);
+ InstallDefaultHandler(kExceptionSignals[i]);
}
}
handlers_installed = false;
@@ -323,7 +341,7 @@ void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
if (sigaction(sig, &cur_handler, NULL) == -1) {
// When resetting the handler fails, try to reset the
// default one to avoid an infinite loop here.
- signal(sig, SIG_DFL);
+ InstallDefaultHandler(sig);
}
pthread_mutex_unlock(&g_handler_stack_mutex_);
return;
@@ -340,7 +358,7 @@ void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
// previously installed handler. Then, when the signal is retriggered, it will
// be delivered to the appropriate handler.
if (handled) {
- signal(sig, SIG_DFL);
+ InstallDefaultHandler(sig);
} else {
RestoreHandlersLocked();
}