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);