summaryrefslogtreecommitdiffstats
path: root/libbacktrace/BacktraceCurrent.cpp
diff options
context:
space:
mode:
authorChristopher Ferris <cferris@google.com>2016-03-09 14:35:54 -0800
committerChristopher Ferris <cferris@google.com>2016-03-10 14:14:43 -0800
commitc463ba45c42b4e2d8ce30c02a626d7183102f46e (patch)
tree4e68f1cb0a203371c57ef864def5acc4178a5d7f /libbacktrace/BacktraceCurrent.cpp
parent01d76eb1ecb943db042eb6618087c0e22588e6b3 (diff)
downloadsystem_core-c463ba45c42b4e2d8ce30c02a626d7183102f46e.tar.gz
system_core-c463ba45c42b4e2d8ce30c02a626d7183102f46e.tar.bz2
system_core-c463ba45c42b4e2d8ce30c02a626d7183102f46e.zip
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
Diffstat (limited to 'libbacktrace/BacktraceCurrent.cpp')
-rw-r--r--libbacktrace/BacktraceCurrent.cpp22
1 files changed, 20 insertions, 2 deletions
diff --git a/libbacktrace/BacktraceCurrent.cpp b/libbacktrace/BacktraceCurrent.cpp
index 8e223668e..5173e2cc9 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 @@ size_t BacktraceCurrent::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) {
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 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) {
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 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) {
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);