aboutsummaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
authorthestig@chromium.org <thestig@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e>2010-08-17 02:59:01 +0000
committerthestig@chromium.org <thestig@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e>2010-08-17 02:59:01 +0000
commit0b12b34928463fee8d808ef17192ef6ba8a72516 (patch)
tree7f31741b3c82169400e5aaa01fa56a4f74bf5373 /src/client
parentremove trailing comma that makes gcc -pedantic unhappy (diff)
downloadbreakpad-0b12b34928463fee8d808ef17192ef6ba8a72516.tar.xz
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
Diffstat (limited to 'src/client')
-rw-r--r--src/client/linux/handler/exception_handler.cc28
1 files 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 {