summaryrefslogtreecommitdiffstats
path: root/libbacktrace/BacktraceThread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libbacktrace/BacktraceThread.cpp')
-rw-r--r--libbacktrace/BacktraceThread.cpp106
1 files changed, 55 insertions, 51 deletions
diff --git a/libbacktrace/BacktraceThread.cpp b/libbacktrace/BacktraceThread.cpp
index 6c3641e..8e664c4 100644
--- a/libbacktrace/BacktraceThread.cpp
+++ b/libbacktrace/BacktraceThread.cpp
@@ -31,55 +31,55 @@
// ThreadEntry implementation.
//-------------------------------------------------------------------------
static ThreadEntry* g_list = NULL;
-static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t g_entry_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t g_sigaction_mutex = PTHREAD_MUTEX_INITIALIZER;
ThreadEntry::ThreadEntry(
BacktraceThreadInterface* intf, pid_t pid, pid_t tid, size_t num_ignore_frames)
- : thread_intf_(intf), pid_(pid), tid_(tid), next_(NULL), prev_(NULL),
- state_(STATE_WAITING), num_ignore_frames_(num_ignore_frames) {
+ : thread_intf(intf), pid(pid), tid(tid), next(NULL), prev(NULL),
+ state(STATE_WAITING), num_ignore_frames(num_ignore_frames) {
}
ThreadEntry::~ThreadEntry() {
- pthread_mutex_lock(&g_mutex);
+ pthread_mutex_lock(&g_entry_mutex);
if (g_list == this) {
- g_list = next_;
+ g_list = next;
} else {
- if (next_) {
- next_->prev_ = prev_;
+ if (next) {
+ next->prev = prev;
}
- prev_->next_ = next_;
+ prev->next = next;
}
- pthread_mutex_unlock(&g_mutex);
+ pthread_mutex_unlock(&g_entry_mutex);
- next_ = NULL;
- prev_ = NULL;
+ next = NULL;
+ prev = NULL;
}
ThreadEntry* ThreadEntry::AddThreadToUnwind(
BacktraceThreadInterface* intf, pid_t pid, pid_t tid, size_t num_ignore_frames) {
ThreadEntry* entry = new ThreadEntry(intf, pid, tid, num_ignore_frames);
- pthread_mutex_lock(&g_mutex);
+ pthread_mutex_lock(&g_entry_mutex);
ThreadEntry* cur_entry = g_list;
while (cur_entry != NULL) {
if (cur_entry->Match(pid, tid)) {
// There is already an entry for this pid/tid, this is bad.
- ALOGW("%s::%s(): Entry for pid %d tid %d already exists.\n",
- __FILE__, __FUNCTION__, pid, tid);
+ BACK_LOGW("Entry for pid %d tid %d already exists.", pid, tid);
- pthread_mutex_unlock(&g_mutex);
+ pthread_mutex_unlock(&g_entry_mutex);
return NULL;
}
- cur_entry = cur_entry->next_;
+ cur_entry = cur_entry->next;
}
// Add the entry to the list.
- entry->next_ = g_list;
+ entry->next = g_list;
if (g_list) {
- g_list->prev_ = entry;
+ g_list->prev = entry;
}
g_list = entry;
- pthread_mutex_unlock(&g_mutex);
+ pthread_mutex_unlock(&g_entry_mutex);
return entry;
}
@@ -89,7 +89,7 @@ ThreadEntry* ThreadEntry::AddThreadToUnwind(
//-------------------------------------------------------------------------
static void SignalHandler(int n __attribute__((unused)), siginfo_t* siginfo,
void* sigcontext) {
- if (pthread_mutex_lock(&g_mutex) == 0) {
+ if (pthread_mutex_lock(&g_entry_mutex) == 0) {
pid_t pid = getpid();
pid_t tid = gettid();
ThreadEntry* cur_entry = g_list;
@@ -97,20 +97,19 @@ static void SignalHandler(int n __attribute__((unused)), siginfo_t* siginfo,
if (cur_entry->Match(pid, tid)) {
break;
}
- cur_entry = cur_entry->next_;
+ cur_entry = cur_entry->next;
}
- pthread_mutex_unlock(&g_mutex);
+ pthread_mutex_unlock(&g_entry_mutex);
if (!cur_entry) {
- ALOGW("%s::%s(): Unable to find pid %d tid %d information\n",
- __FILE__, __FUNCTION__, pid, tid);
+ BACK_LOGW("Unable to find pid %d tid %d information", pid, tid);
return;
}
- if (android_atomic_acquire_cas(STATE_WAITING, STATE_DUMPING, &cur_entry->state_) == 0) {
- cur_entry->thread_intf_->ThreadUnwind(siginfo, sigcontext,
- cur_entry->num_ignore_frames_);
+ if (android_atomic_acquire_cas(STATE_WAITING, STATE_DUMPING, &cur_entry->state) == 0) {
+ cur_entry->thread_intf->ThreadUnwind(siginfo, sigcontext,
+ cur_entry->num_ignore_frames);
}
- android_atomic_release_store(STATE_DONE, &cur_entry->state_);
+ android_atomic_release_store(STATE_DONE, &cur_entry->state);
}
}
@@ -143,18 +142,18 @@ void BacktraceThread::FinishUnwind() {
}
bool BacktraceThread::TriggerUnwindOnThread(ThreadEntry* entry) {
- entry->state_ = STATE_WAITING;
+ entry->state = STATE_WAITING;
if (tgkill(Pid(), Tid(), SIGURG) != 0) {
- ALOGW("%s::%s(): tgkill failed %s\n", __FILE__, __FUNCTION__, strerror(errno));
+ BACK_LOGW("tgkill failed %s", strerror(errno));
return false;
}
- // Allow up to a second for the dump to occur.
- int wait_millis = 1000;
+ // Allow up to ten seconds for the dump to start.
+ int wait_millis = 10000;
int32_t state;
while (true) {
- state = android_atomic_acquire_load(&entry->state_);
+ state = android_atomic_acquire_load(&entry->state);
if (state != STATE_WAITING) {
break;
}
@@ -167,24 +166,22 @@ bool BacktraceThread::TriggerUnwindOnThread(ThreadEntry* entry) {
bool cancelled = false;
if (state == STATE_WAITING) {
- if (android_atomic_acquire_cas(state, STATE_CANCEL, &entry->state_) == 0) {
- ALOGW("%s::%s(): Cancelled dump of thread %d\n", __FILE__, __FUNCTION__,
- entry->tid_);
+ if (android_atomic_acquire_cas(state, STATE_CANCEL, &entry->state) == 0) {
+ BACK_LOGW("Cancelled dump of thread %d", entry->tid);
state = STATE_CANCEL;
cancelled = true;
} else {
- state = android_atomic_acquire_load(&entry->state_);
+ state = android_atomic_acquire_load(&entry->state);
}
}
- // Wait for at most one minute for the dump to finish.
- wait_millis = 60000;
- while (android_atomic_acquire_load(&entry->state_) != STATE_DONE) {
+ // Wait for at most ten seconds for the cancel or dump to finish.
+ wait_millis = 10000;
+ while (android_atomic_acquire_load(&entry->state) != STATE_DONE) {
if (wait_millis--) {
usleep(1000);
} else {
- ALOGW("%s::%s(): Didn't finish thread unwind in 60 seconds.\n",
- __FILE__, __FUNCTION__);
+ BACK_LOGW("Didn't finish thread unwind in 60 seconds.");
break;
}
}
@@ -202,17 +199,24 @@ bool BacktraceThread::Unwind(size_t num_ignore_frames) {
return false;
}
+ // Prevent multiple threads trying to set the trigger action on different
+ // threads at the same time.
bool retval = false;
- struct sigaction act, oldact;
- memset(&act, 0, sizeof(act));
- act.sa_sigaction = SignalHandler;
- act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
- sigemptyset(&act.sa_mask);
- if (sigaction(SIGURG, &act, &oldact) == 0) {
- retval = TriggerUnwindOnThread(entry);
- sigaction(SIGURG, &oldact, NULL);
+ if (pthread_mutex_lock(&g_sigaction_mutex) == 0) {
+ struct sigaction act, oldact;
+ memset(&act, 0, sizeof(act));
+ act.sa_sigaction = SignalHandler;
+ act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
+ sigemptyset(&act.sa_mask);
+ if (sigaction(SIGURG, &act, &oldact) == 0) {
+ retval = TriggerUnwindOnThread(entry);
+ sigaction(SIGURG, &oldact, NULL);
+ } else {
+ BACK_LOGW("sigaction failed %s", strerror(errno));
+ }
+ pthread_mutex_unlock(&g_sigaction_mutex);
} else {
- ALOGW("%s::%s(): sigaction failed %s\n", __FILE__, __FUNCTION__, strerror(errno));
+ BACK_LOGW("unable to acquire sigaction mutex.");
}
if (retval) {