Add error reporting mechanism for failing Unwind.

Remove the logging of an error if a thread disappears before the unwind
can begin. This can happen, so allow the caller to determine if this
is really a problem worth logging.

Bug: 27449879

(cherry picked from commit 206a3b9798e3622c906a3cafdb113c271c1c927c)

Change-Id: If9e7cfeb6eb7b122679a734c1a9eacee8354ef18
diff --git a/libbacktrace/BacktraceCurrent.cpp b/libbacktrace/BacktraceCurrent.cpp
index 8e22366..5173e2c 100644
--- a/libbacktrace/BacktraceCurrent.cpp
+++ b/libbacktrace/BacktraceCurrent.cpp
@@ -24,6 +24,8 @@
 #include <ucontext.h>
 #include <unistd.h>
 
+#include <stdlib.h>
+
 #include <string>
 
 #include <backtrace/Backtrace.h>
@@ -65,9 +67,11 @@
 bool BacktraceCurrent::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) {
   if (GetMap() == nullptr) {
     // Without a map object, we can't do anything.
+    error_ = BACKTRACE_UNWIND_ERROR_MAP_MISSING;
     return false;
   }
 
+  error_ = BACKTRACE_UNWIND_NO_ERROR;
   if (ucontext) {
     return UnwindFromContext(num_ignore_frames, ucontext);
   }
@@ -138,11 +142,19 @@
     BACK_LOGE("sigaction failed: %s", strerror(errno));
     ThreadEntry::Remove(entry);
     pthread_mutex_unlock(&g_sigaction_mutex);
+    error_ = BACKTRACE_UNWIND_ERROR_INTERNAL;
     return false;
   }
 
   if (tgkill(Pid(), Tid(), THREAD_SIGNAL) != 0) {
-    BACK_LOGE("tgkill %d failed: %s", Tid(), strerror(errno));
+    // Do not emit an error message, this might be expected. Set the
+    // error and let the caller decide.
+    if (errno == ESRCH) {
+      error_ = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST;
+    } else {
+      error_ = BACKTRACE_UNWIND_ERROR_INTERNAL;
+    }
+
     sigaction(THREAD_SIGNAL, &oldact, nullptr);
     ThreadEntry::Remove(entry);
     pthread_mutex_unlock(&g_sigaction_mutex);
@@ -183,7 +195,13 @@
       BACK_LOGW("Timed out waiting for signal handler to indicate it finished.");
     }
   } else {
-    BACK_LOGE("Timed out waiting for signal handler to get ucontext data.");
+    // Check to see if the thread has disappeared.
+    if (tgkill(Pid(), Tid(), 0) == -1 && errno == ESRCH) {
+      error_ = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST;
+    } else {
+      error_ = BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT;
+      BACK_LOGE("Timed out waiting for signal handler to get ucontext data.");
+    }
   }
 
   ThreadEntry::Remove(entry);