From 0b12b34928463fee8d808ef17192ef6ba8a72516 Mon Sep 17 00:00:00 2001 From: "thestig@chromium.org" Date: Tue, 17 Aug 2010 02:59:01 +0000 Subject: [PATCH] When done with crash-dumping, we need to terminate the application. Calling tgkill() is not necessarily possible, as a sandbox might block this call. This changelist tries different approaches depending on whether we received a synchronous or an asynchronous signal. This fixes unittest failures and also runs correctly in sandbox'd environments. TEST=ran unittest, and opened about:crash in sandbox'd Chrome BUG=395 A=markus@chromium.org Original review: http://breakpad.appspot.com/159001 Review URL: http://breakpad.appspot.com/146002 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@656 4c0a9323-5329-0410-9bdc-e9ce6186880e --- src/client/linux/handler/exception_handler.cc | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/client/linux/handler/exception_handler.cc b/src/client/linux/handler/exception_handler.cc index 6e58ff2c..f3a7aa85 100644 --- a/src/client/linux/handler/exception_handler.cc +++ b/src/client/linux/handler/exception_handler.cc @@ -265,16 +265,28 @@ void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) { pthread_mutex_unlock(&handler_stack_mutex_); - // Terminate ourselves with the same signal so that our parent knows that we - // crashed. The default action for all the signals which we catch is Core, so + if (info->si_pid) { + // 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. + if (tgkill(getpid(), syscall(__NR_gettid), sig) < 0) { + // If we failed to kill ourselves (e.g. because a sandbox disallows us + // to do so), we instead resort to terminating our process. This will + // result in an incorrect exit code. + _exit(1); + } + } else { + // This was a synchronous signal triggered by a hard fault (e.g. SIGSEGV). + // No need to reissue the signal. It will automatically trigger again, + // when we return from the signal handler. + } + + // As soon as we return from the signal handler, our signal will become + // unmasked. At that time, we will get terminated with the same signal that + // was triggered originally. This allows our parent to know that we crashed. + // The default action for all the signals which we catch is Core, so // this is the end of us. signal(sig, SIG_DFL); - - // TODO(markus): mask signal and return to caller - tgkill(getpid(), syscall(__NR_gettid), sig); - _exit(1); - - // not reached. } struct ThreadArgument {