diff options
author | mark@chromium.org <mark@chromium.org> | 2015-04-10 17:57:24 +0000 |
---|---|---|
committer | mark@chromium.org <mark@chromium.org> | 2015-04-10 17:57:24 +0000 |
commit | cfdf7cf8a97fbd5651ce0c22735b8a26904749e6 (patch) | |
tree | 2bc74b7c8b7073cbd9574b9bb20cc24531cde383 /src/client | |
parent | Fix compilation with gcc --std=c++11 (diff) | |
download | breakpad-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')
-rw-r--r-- | src/client/linux/handler/exception_handler.cc | 24 |
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(); } |