[DO NOT MERGE] Improve signal catching and native stack dumps.

This works around the problem with abort(3) (and friends) on glibc,
and improves our ability to catch SIGSEGVs from the main thread, and
slightly improves our behavior if multiple threads are dying at once.
I think any remaining flakiness is only in this last case, and I'm
not sure whether we can actually improve that any further.

(cherry picked from commit dcaaea9d30f39622d0b1d9bbb68911173621e54b)

Conflicts:

	src/runtime_linux.cc

Change-Id: I9922f3ee4609799993635e1ed98a21363505a6ab
diff --git a/src/runtime_linux.cc b/src/runtime_linux.cc
index e2c806d..3e39fa2 100644
--- a/src/runtime_linux.cc
+++ b/src/runtime_linux.cc
@@ -258,6 +258,9 @@
 };
 
 static void HandleUnexpectedSignal(int signal_number, siginfo_t* info, void* raw_context) {
+  static Mutex unexpected_signal_lock("unexpected signal lock");
+  MutexLock mu(unexpected_signal_lock);
+
   bool has_address = (signal_number == SIGILL || signal_number == SIGBUS ||
                       signal_number == SIGFPE || signal_number == SIGSEGV);
 
@@ -283,6 +286,15 @@
     while (true) {
     }
   }
+
+  // Remove our signal handler for this signal...
+  struct sigaction action;
+  memset(&action, 0, sizeof(action));
+  sigemptyset(&action.sa_mask);
+  action.sa_handler = SIG_DFL;
+  sigaction(signal_number, &action, NULL);
+  // ...and re-raise so we die with the appropriate status.
+  kill(getpid(), signal_number);
 }
 
 void Runtime::InitPlatformSignalHandlers() {
@@ -291,11 +303,12 @@
   memset(&action, 0, sizeof(action));
   sigemptyset(&action.sa_mask);
   action.sa_sigaction = HandleUnexpectedSignal;
-  action.sa_flags = SA_RESTART;
   // Use the three-argument sa_sigaction handler.
   action.sa_flags |= SA_SIGINFO;
-  // Remove ourselves as signal handler for this signal, in case of recursion.
-  action.sa_flags |= SA_RESETHAND;
+#if !defined(__APPLE__)
+  // Use the alternate signal stack so we can catch stack overflows.
+  action.sa_flags |= SA_ONSTACK;
+#endif
 
   int rc = 0;
   rc += sigaction(SIGILL, &action, NULL);