mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2025-01-28 04:30:59 +00:00
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
This commit is contained in:
parent
48b9a40539
commit
cfdf7cf8a9
|
@ -188,6 +188,24 @@ void RestoreAlternateStackLocked() {
|
||||||
stack_installed = false;
|
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
|
// The global exception handler stack. This is needed because there may exist
|
||||||
// multiple ExceptionHandler instances in a process. Each will have itself
|
// multiple ExceptionHandler instances in a process. Each will have itself
|
||||||
// registered in this stack.
|
// registered in this stack.
|
||||||
|
@ -283,7 +301,7 @@ void ExceptionHandler::RestoreHandlersLocked() {
|
||||||
|
|
||||||
for (int i = 0; i < kNumHandledSignals; ++i) {
|
for (int i = 0; i < kNumHandledSignals; ++i) {
|
||||||
if (sigaction(kExceptionSignals[i], &old_handlers[i], NULL) == -1) {
|
if (sigaction(kExceptionSignals[i], &old_handlers[i], NULL) == -1) {
|
||||||
signal(kExceptionSignals[i], SIG_DFL);
|
InstallDefaultHandler(kExceptionSignals[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
handlers_installed = false;
|
handlers_installed = false;
|
||||||
|
@ -323,7 +341,7 @@ void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
|
||||||
if (sigaction(sig, &cur_handler, NULL) == -1) {
|
if (sigaction(sig, &cur_handler, NULL) == -1) {
|
||||||
// When resetting the handler fails, try to reset the
|
// When resetting the handler fails, try to reset the
|
||||||
// default one to avoid an infinite loop here.
|
// default one to avoid an infinite loop here.
|
||||||
signal(sig, SIG_DFL);
|
InstallDefaultHandler(sig);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&g_handler_stack_mutex_);
|
pthread_mutex_unlock(&g_handler_stack_mutex_);
|
||||||
return;
|
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
|
// previously installed handler. Then, when the signal is retriggered, it will
|
||||||
// be delivered to the appropriate handler.
|
// be delivered to the appropriate handler.
|
||||||
if (handled) {
|
if (handled) {
|
||||||
signal(sig, SIG_DFL);
|
InstallDefaultHandler(sig);
|
||||||
} else {
|
} else {
|
||||||
RestoreHandlersLocked();
|
RestoreHandlersLocked();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue