Only one crashing thread should contact debuggerd.

If two or more threads crash at the same time, only let one talk to
debuggerd. It's possible for a race to occur that two threads send
data to debuggerd, the second one will cause errors in debuggerd since
the process will die once debuggerd lets the crashing pid start again.

Bug: 19183955
Change-Id: I17dfce46102117ab4a870f7381bd526488d37fb5
diff --git a/linker/debugger.cpp b/linker/debugger.cpp
index c889544..6fe9524 100644
--- a/linker/debugger.cpp
+++ b/linker/debugger.cpp
@@ -30,9 +30,11 @@
 
 #include <errno.h>
 #include <inttypes.h>
+#include <pthread.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/mman.h>
 #include <sys/prctl.h>
 #include <sys/socket.h>
@@ -212,6 +214,23 @@
     return;
   }
 
+  // Mutex to prevent multiple crashing threads from trying to talk
+  // to debuggerd at the same time.
+  static pthread_mutex_t crash_mutex = PTHREAD_MUTEX_INITIALIZER;
+  int ret = pthread_mutex_trylock(&crash_mutex);
+  if (ret != 0) {
+    if (ret == EBUSY) {
+      __libc_format_log(ANDROID_LOG_INFO, "libc",
+                        "Another thread has contacted debuggerd first, stop and wait for process to die.");
+      // This will never complete since the lock is never released.
+      pthread_mutex_lock(&crash_mutex);
+    } else {
+      __libc_format_log(ANDROID_LOG_INFO, "libc",
+                        "pthread_mutex_trylock failed: %s", strerror(ret));
+    }
+    return;
+  }
+
   int s = socket_abstract_client(DEBUGGER_SOCKET_NAME, SOCK_STREAM | SOCK_CLOEXEC);
   if (s == -1) {
     __libc_format_log(ANDROID_LOG_FATAL, "libc", "Unable to open connection to debuggerd: %s",
@@ -228,7 +247,7 @@
   msg.tid = gettid();
   msg.abort_msg_address = reinterpret_cast<uintptr_t>(g_abort_message);
   msg.original_si_code = (info != nullptr) ? info->si_code : 0;
-  int ret = TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg)));
+  ret = TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg)));
   if (ret == sizeof(msg)) {
     char debuggerd_ack;
     ret = TEMP_FAILURE_RETRY(read(s, &debuggerd_ack, 1));