BacktraceThread.cpp revision e48460762273586744a79d146c2916bcfca7e9e4
117e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris/* 217e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris * Copyright (C) 2013 The Android Open Source Project 317e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris * 417e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris * Licensed under the Apache License, Version 2.0 (the "License"); 517e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris * you may not use this file except in compliance with the License. 617e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris * You may obtain a copy of the License at 717e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris * 817e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris * http://www.apache.org/licenses/LICENSE-2.0 917e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris * 1017e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris * Unless required by applicable law or agreed to in writing, software 1117e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris * distributed under the License is distributed on an "AS IS" BASIS, 1217e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1317e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris * See the License for the specific language governing permissions and 1417e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris * limitations under the License. 1517e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris */ 1617e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 1717e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris#include <errno.h> 1817e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris#include <inttypes.h> 19a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris#include <limits.h> 20a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris#include <linux/futex.h> 2117e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris#include <pthread.h> 2217e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris#include <signal.h> 2317e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris#include <string.h> 24a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris#include <sys/syscall.h> 25a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris#include <sys/time.h> 2617e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris#include <sys/types.h> 27a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris#include <ucontext.h> 2817e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 2917e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris#include <cutils/atomic.h> 3017e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 31e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris#include "BacktraceLog.h" 3217e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris#include "BacktraceThread.h" 3317e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris#include "thread_utils.h" 3417e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 35a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferrisstatic inline int futex(volatile int* uaddr, int op, int val, const struct timespec* ts, volatile int* uaddr2, int val3) { 36a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris return syscall(__NR_futex, uaddr, op, val, ts, uaddr2, val3); 37a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris} 38a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris 3917e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris//------------------------------------------------------------------------- 4017e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris// ThreadEntry implementation. 4117e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris//------------------------------------------------------------------------- 42a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher FerrisThreadEntry* ThreadEntry::list_ = NULL; 43a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferrispthread_mutex_t ThreadEntry::list_mutex_ = PTHREAD_MUTEX_INITIALIZER; 44a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris 45a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris// Assumes that ThreadEntry::list_mutex_ has already been locked before 46a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris// creating a ThreadEntry object. 47a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher FerrisThreadEntry::ThreadEntry(pid_t pid, pid_t tid) 48a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris : pid_(pid), tid_(tid), futex_(0), ref_count_(1), mutex_(PTHREAD_MUTEX_INITIALIZER), next_(ThreadEntry::list_), prev_(NULL) { 49a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris // Add ourselves to the list. 50a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris if (ThreadEntry::list_) { 51a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris ThreadEntry::list_->prev_ = this; 52a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris } 53a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris ThreadEntry::list_ = this; 5417e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris} 5517e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 56a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher FerrisThreadEntry* ThreadEntry::Get(pid_t pid, pid_t tid, bool create) { 57a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris pthread_mutex_lock(&ThreadEntry::list_mutex_); 58a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris ThreadEntry* entry = list_; 59a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris while (entry != NULL) { 60a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris if (entry->Match(pid, tid)) { 61a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris break; 6217e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris } 63a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris entry = entry->next_; 6417e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris } 6517e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 66a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris if (!entry) { 67a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris if (create) { 68a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris entry = new ThreadEntry(pid, tid); 69a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris } 70a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris } else { 71a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris entry->ref_count_++; 72a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris } 73a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris pthread_mutex_unlock(&ThreadEntry::list_mutex_); 74a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris 75a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris return entry; 7617e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris} 7717e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 78a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferrisvoid ThreadEntry::Remove(ThreadEntry* entry) { 79a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris pthread_mutex_unlock(&entry->mutex_); 8017e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 81a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris pthread_mutex_lock(&ThreadEntry::list_mutex_); 82a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris if (--entry->ref_count_ == 0) { 83a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris delete entry; 84a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris } 85a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris pthread_mutex_unlock(&ThreadEntry::list_mutex_); 86a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris} 8717e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 88a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris// Assumes that ThreadEntry::list_mutex_ has already been locked before 89a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris// deleting a ThreadEntry object. 90a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher FerrisThreadEntry::~ThreadEntry() { 91a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris if (list_ == this) { 92a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris list_ = next_; 93a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris } else { 94a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris if (next_) { 95a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris next_->prev_ = prev_; 9617e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris } 97a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris prev_->next_ = next_; 9817e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris } 9917e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 100a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris next_ = NULL; 101a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris prev_ = NULL; 102a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris} 103a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris 104a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferrisvoid ThreadEntry::Wait(int value) { 105a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris timespec ts; 106a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris ts.tv_sec = 10; 107a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris ts.tv_nsec = 0; 108a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris errno = 0; 109a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris futex(&futex_, FUTEX_WAIT, value, &ts, NULL, 0); 110a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris if (errno != 0 && errno != EWOULDBLOCK) { 111a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris BACK_LOGW("futex wait failed, futex = %d: %s", futex_, strerror(errno)); 11217e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris } 113a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris} 11417e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 115a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferrisvoid ThreadEntry::Wake() { 116a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris futex_++; 117a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris futex(&futex_, FUTEX_WAKE, INT_MAX, NULL, NULL, 0); 11817e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris} 11917e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 120e48460762273586744a79d146c2916bcfca7e9e4Christopher Ferrisvoid ThreadEntry::CopyUcontextFromSigcontext(void* sigcontext) { 121e48460762273586744a79d146c2916bcfca7e9e4Christopher Ferris ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(sigcontext); 122e48460762273586744a79d146c2916bcfca7e9e4Christopher Ferris // The only thing the unwinder cares about is the mcontext data. 123e48460762273586744a79d146c2916bcfca7e9e4Christopher Ferris memcpy(&ucontext_.uc_mcontext, &ucontext->uc_mcontext, sizeof(ucontext->uc_mcontext)); 124e48460762273586744a79d146c2916bcfca7e9e4Christopher Ferris} 125e48460762273586744a79d146c2916bcfca7e9e4Christopher Ferris 12617e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris//------------------------------------------------------------------------- 12717e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris// BacktraceThread functions. 12817e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris//------------------------------------------------------------------------- 129a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferrisstatic pthread_mutex_t g_sigaction_mutex = PTHREAD_MUTEX_INITIALIZER; 13017e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 131a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferrisstatic void SignalHandler(int, siginfo_t*, void* sigcontext) { 132a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris ThreadEntry* entry = ThreadEntry::Get(getpid(), gettid(), false); 133a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris if (!entry) { 134a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris BACK_LOGW("Unable to find pid %d tid %d information", getpid(), gettid()); 135a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris return; 13617e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris } 137a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris 138e48460762273586744a79d146c2916bcfca7e9e4Christopher Ferris entry->CopyUcontextFromSigcontext(sigcontext); 139a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris 140a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris // Indicate the ucontext is now valid. 141a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris entry->Wake(); 142a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris 143a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris // Pause the thread until the unwind is complete. This avoids having 144a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris // the thread run ahead causing problems. 145a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris entry->Wait(1); 146a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris 147a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris ThreadEntry::Remove(entry); 14817e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris} 14917e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 150a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher FerrisBacktraceThread::BacktraceThread(BacktraceImpl* impl, pid_t tid, BacktraceMap* map) 151a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris : BacktraceCurrent(impl, map) { 15246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris tid_ = tid; 15317e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris} 15417e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 15517e91d44edf5e6476a477a200bcd89d4327358a3Christopher FerrisBacktraceThread::~BacktraceThread() { 15617e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris} 15717e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 158a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferrisbool BacktraceThread::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) { 159a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris if (ucontext) { 160a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris // Unwind using an already existing ucontext. 161a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris return impl_->Unwind(num_ignore_frames, ucontext); 16217e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris } 16317e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 164a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris // Prevent multiple threads trying to set the trigger action on different 165a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris // threads at the same time. 166a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris if (pthread_mutex_lock(&g_sigaction_mutex) < 0) { 167a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris BACK_LOGW("sigaction failed: %s", strerror(errno)); 16817e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris return false; 16917e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris } 17017e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 171a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris ThreadEntry* entry = ThreadEntry::Get(Pid(), Tid()); 172a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris entry->Lock(); 173a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris 174a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris struct sigaction act, oldact; 175a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris memset(&act, 0, sizeof(act)); 176a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris act.sa_sigaction = SignalHandler; 177a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; 178a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris sigemptyset(&act.sa_mask); 179a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris if (sigaction(THREAD_SIGNAL, &act, &oldact) != 0) { 180a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris BACK_LOGW("sigaction failed %s", strerror(errno)); 181a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris entry->Unlock(); 182a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris ThreadEntry::Remove(entry); 183a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris pthread_mutex_unlock(&g_sigaction_mutex); 184a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris return false; 18517e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris } 18617e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 187a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris if (tgkill(Pid(), Tid(), THREAD_SIGNAL) != 0) { 188a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris BACK_LOGW("tgkill %d failed: %s", Tid(), strerror(errno)); 189a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris sigaction(THREAD_SIGNAL, &oldact, NULL); 190a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris entry->Unlock(); 191a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris ThreadEntry::Remove(entry); 192a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris pthread_mutex_unlock(&g_sigaction_mutex); 193a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris return false; 19417e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris } 19517e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 196a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris // Wait for the thread to get the ucontext. 197a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris entry->Wait(0); 19817e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 199a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris // After the thread has received the signal, allow other unwinders to 200a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris // continue. 201a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris sigaction(THREAD_SIGNAL, &oldact, NULL); 202a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris pthread_mutex_unlock(&g_sigaction_mutex); 20317e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 204a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris bool unwind_done = impl_->Unwind(num_ignore_frames, entry->GetUcontext()); 20517e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 206a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris // Tell the signal handler to exit and release the entry. 207a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris entry->Wake(); 20817e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris 209a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris return unwind_done; 21017e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris} 211