Loading include/backtrace/Backtrace.h +12 −11 Original line number Diff line number Diff line Loading @@ -25,7 +25,16 @@ class BacktraceImpl; class Backtrace { public: Backtrace(BacktraceImpl* impl); // Create the correct Backtrace object based on what is to be unwound. // If pid < 0 or equals the current pid, then the Backtrace object // corresponds to the current process. // If pid < 0 or equals the current pid and tid >= 0, then the Backtrace // object corresponds to a thread in the current process. // If pid >= 0 and tid < 0, then the Backtrace object corresponds to a // different process. // Tracing a thread in a different process is not supported. static Backtrace* Create(pid_t pid, pid_t tid); virtual ~Backtrace(); // Get the current stack trace and store in the backtrace_ structure. Loading Loading @@ -60,17 +69,9 @@ public: return &backtrace_.frames[frame_num]; } // Create the correct Backtrace object based on what is to be unwound. // If pid < 0 or equals the current pid, then the Backtrace object // corresponds to the current process. // If pid < 0 or equals the current pid and tid >= 0, then the Backtrace // object corresponds to a thread in the current process. // If pid >= 0 and tid < 0, then the Backtrace object corresponds to a // different process. // Tracing a thread in a different process is not supported. static Backtrace* Create(pid_t pid, pid_t tid); protected: Backtrace(BacktraceImpl* impl); virtual bool VerifyReadWordArgs(uintptr_t ptr, uint32_t* out_value); BacktraceImpl* impl_; Loading libbacktrace/Backtrace.cpp +9 −14 Original line number Diff line number Diff line Loading @@ -72,10 +72,8 @@ bool Backtrace::Unwind(size_t num_ignore_frames) { return impl_->Unwind(num_ignore_frames); } __BEGIN_DECLS extern char* __cxa_demangle (const char* mangled, char* buf, size_t* len, extern "C" char* __cxa_demangle(const char* mangled, char* buf, size_t* len, int* status); __END_DECLS std::string Backtrace::GetFunctionName(uintptr_t pc, uintptr_t* offset) { std::string func_name = impl_->GetFunctionNameRaw(pc, offset); Loading @@ -97,7 +95,7 @@ std::string Backtrace::GetFunctionName(uintptr_t pc, uintptr_t* offset) { bool Backtrace::VerifyReadWordArgs(uintptr_t ptr, uint32_t* out_value) { if (ptr & 3) { ALOGW("Backtrace::verifyReadWordArgs: invalid pointer %p", (void*)ptr); BACK_LOGW("invalid pointer %p", (void*)ptr); *out_value = (uint32_t)-1; return false; } Loading Loading @@ -172,7 +170,7 @@ bool BacktraceCurrent::ReadWord(uintptr_t ptr, uint32_t* out_value) { *out_value = *reinterpret_cast<uint32_t*>(ptr); return true; } else { ALOGW("BacktraceCurrent::readWord: pointer %p not in a readbale map", reinterpret_cast<void*>(ptr)); BACK_LOGW("pointer %p not in a readable map", reinterpret_cast<void*>(ptr)); *out_value = static_cast<uint32_t>(-1); return false; } Loading @@ -198,7 +196,7 @@ bool BacktracePtrace::ReadWord(uintptr_t ptr, uint32_t* out_value) { } #if defined(__APPLE__) ALOGW("BacktracePtrace::readWord: MacOS does not support reading from another pid.\n"); BACK_LOGW("MacOS does not support reading from another pid."); return false; #else // ptrace() returns -1 and sets errno when the operation fails. Loading @@ -206,8 +204,8 @@ bool BacktracePtrace::ReadWord(uintptr_t ptr, uint32_t* out_value) { errno = 0; *out_value = ptrace(PTRACE_PEEKTEXT, Tid(), reinterpret_cast<void*>(ptr), NULL); if (*out_value == static_cast<uint32_t>(-1) && errno) { ALOGW("BacktracePtrace::readWord: invalid pointer 0x%08x reading from tid %d, " "ptrace() errno=%d", ptr, Tid(), errno); BACK_LOGW("invalid pointer %p reading from tid %d, ptrace() strerror(errno)=%s", reinterpret_cast<void*>(ptr), Tid(), strerror(errno)); return false; } return true; Loading Loading @@ -295,11 +293,8 @@ void backtrace_format_frame_data( const backtrace_context_t* context, size_t frame_num, char* buf, size_t buf_size) { if (buf_size == 0 || buf == NULL) { ALOGW("backtrace_format_frame_data: bad call buf %p buf_size %zu\n", buf, buf_size); return; } if (context->data) { BACK_LOGW("bad call buf %p buf_size %zu", buf, buf_size); } else if (context->data) { Backtrace* backtrace = reinterpret_cast<Backtrace*>(context->data); std::string line = backtrace->FormatFrameData(frame_num); if (line.size() > buf_size) { Loading libbacktrace/Backtrace.h +4 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,10 @@ #include <sys/types.h> // Macro to log the function name along with the warning message. #define BACK_LOGW(format, ...) \ ALOGW("%s: " format, __PRETTY_FUNCTION__, ##__VA_ARGS__) class BacktraceImpl { public: virtual ~BacktraceImpl() { } Loading libbacktrace/BacktraceThread.cpp +55 −51 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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; Loading @@ -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); } } Loading Loading @@ -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; } Loading @@ -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; } } Loading @@ -202,7 +199,10 @@ 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; if (pthread_mutex_lock(&g_sigaction_mutex) == 0) { struct sigaction act, oldact; memset(&act, 0, sizeof(act)); act.sa_sigaction = SignalHandler; Loading @@ -212,7 +212,11 @@ bool BacktraceThread::Unwind(size_t num_ignore_frames) { retval = TriggerUnwindOnThread(entry); sigaction(SIGURG, &oldact, NULL); } else { ALOGW("%s::%s(): sigaction failed %s\n", __FILE__, __FUNCTION__, strerror(errno)); BACK_LOGW("sigaction failed %s", strerror(errno)); } pthread_mutex_unlock(&g_sigaction_mutex); } else { BACK_LOGW("unable to acquire sigaction mutex."); } if (retval) { Loading libbacktrace/BacktraceThread.h +9 −10 Original line number Diff line number Diff line Loading @@ -32,26 +32,25 @@ typedef enum { class BacktraceThreadInterface; class ThreadEntry { public: struct ThreadEntry { ThreadEntry( BacktraceThreadInterface* impl, pid_t pid, pid_t tid, size_t num_ignore_frames); ~ThreadEntry(); bool Match(pid_t pid, pid_t tid) { return (pid == pid_ && tid == tid_); } bool Match(pid_t chk_pid, pid_t chk_tid) { return (chk_pid == pid && chk_tid == tid); } static ThreadEntry* AddThreadToUnwind( BacktraceThreadInterface* thread_intf, pid_t pid, pid_t tid, size_t num_ignored_frames); BacktraceThreadInterface* thread_intf_; pid_t pid_; pid_t tid_; ThreadEntry* next_; ThreadEntry* prev_; int32_t state_; int num_ignore_frames_; BacktraceThreadInterface* thread_intf; pid_t pid; pid_t tid; ThreadEntry* next; ThreadEntry* prev; int32_t state; int num_ignore_frames; }; // Interface class that does not contain any local storage, only defines Loading Loading
include/backtrace/Backtrace.h +12 −11 Original line number Diff line number Diff line Loading @@ -25,7 +25,16 @@ class BacktraceImpl; class Backtrace { public: Backtrace(BacktraceImpl* impl); // Create the correct Backtrace object based on what is to be unwound. // If pid < 0 or equals the current pid, then the Backtrace object // corresponds to the current process. // If pid < 0 or equals the current pid and tid >= 0, then the Backtrace // object corresponds to a thread in the current process. // If pid >= 0 and tid < 0, then the Backtrace object corresponds to a // different process. // Tracing a thread in a different process is not supported. static Backtrace* Create(pid_t pid, pid_t tid); virtual ~Backtrace(); // Get the current stack trace and store in the backtrace_ structure. Loading Loading @@ -60,17 +69,9 @@ public: return &backtrace_.frames[frame_num]; } // Create the correct Backtrace object based on what is to be unwound. // If pid < 0 or equals the current pid, then the Backtrace object // corresponds to the current process. // If pid < 0 or equals the current pid and tid >= 0, then the Backtrace // object corresponds to a thread in the current process. // If pid >= 0 and tid < 0, then the Backtrace object corresponds to a // different process. // Tracing a thread in a different process is not supported. static Backtrace* Create(pid_t pid, pid_t tid); protected: Backtrace(BacktraceImpl* impl); virtual bool VerifyReadWordArgs(uintptr_t ptr, uint32_t* out_value); BacktraceImpl* impl_; Loading
libbacktrace/Backtrace.cpp +9 −14 Original line number Diff line number Diff line Loading @@ -72,10 +72,8 @@ bool Backtrace::Unwind(size_t num_ignore_frames) { return impl_->Unwind(num_ignore_frames); } __BEGIN_DECLS extern char* __cxa_demangle (const char* mangled, char* buf, size_t* len, extern "C" char* __cxa_demangle(const char* mangled, char* buf, size_t* len, int* status); __END_DECLS std::string Backtrace::GetFunctionName(uintptr_t pc, uintptr_t* offset) { std::string func_name = impl_->GetFunctionNameRaw(pc, offset); Loading @@ -97,7 +95,7 @@ std::string Backtrace::GetFunctionName(uintptr_t pc, uintptr_t* offset) { bool Backtrace::VerifyReadWordArgs(uintptr_t ptr, uint32_t* out_value) { if (ptr & 3) { ALOGW("Backtrace::verifyReadWordArgs: invalid pointer %p", (void*)ptr); BACK_LOGW("invalid pointer %p", (void*)ptr); *out_value = (uint32_t)-1; return false; } Loading Loading @@ -172,7 +170,7 @@ bool BacktraceCurrent::ReadWord(uintptr_t ptr, uint32_t* out_value) { *out_value = *reinterpret_cast<uint32_t*>(ptr); return true; } else { ALOGW("BacktraceCurrent::readWord: pointer %p not in a readbale map", reinterpret_cast<void*>(ptr)); BACK_LOGW("pointer %p not in a readable map", reinterpret_cast<void*>(ptr)); *out_value = static_cast<uint32_t>(-1); return false; } Loading @@ -198,7 +196,7 @@ bool BacktracePtrace::ReadWord(uintptr_t ptr, uint32_t* out_value) { } #if defined(__APPLE__) ALOGW("BacktracePtrace::readWord: MacOS does not support reading from another pid.\n"); BACK_LOGW("MacOS does not support reading from another pid."); return false; #else // ptrace() returns -1 and sets errno when the operation fails. Loading @@ -206,8 +204,8 @@ bool BacktracePtrace::ReadWord(uintptr_t ptr, uint32_t* out_value) { errno = 0; *out_value = ptrace(PTRACE_PEEKTEXT, Tid(), reinterpret_cast<void*>(ptr), NULL); if (*out_value == static_cast<uint32_t>(-1) && errno) { ALOGW("BacktracePtrace::readWord: invalid pointer 0x%08x reading from tid %d, " "ptrace() errno=%d", ptr, Tid(), errno); BACK_LOGW("invalid pointer %p reading from tid %d, ptrace() strerror(errno)=%s", reinterpret_cast<void*>(ptr), Tid(), strerror(errno)); return false; } return true; Loading Loading @@ -295,11 +293,8 @@ void backtrace_format_frame_data( const backtrace_context_t* context, size_t frame_num, char* buf, size_t buf_size) { if (buf_size == 0 || buf == NULL) { ALOGW("backtrace_format_frame_data: bad call buf %p buf_size %zu\n", buf, buf_size); return; } if (context->data) { BACK_LOGW("bad call buf %p buf_size %zu", buf, buf_size); } else if (context->data) { Backtrace* backtrace = reinterpret_cast<Backtrace*>(context->data); std::string line = backtrace->FormatFrameData(frame_num); if (line.size() > buf_size) { Loading
libbacktrace/Backtrace.h +4 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,10 @@ #include <sys/types.h> // Macro to log the function name along with the warning message. #define BACK_LOGW(format, ...) \ ALOGW("%s: " format, __PRETTY_FUNCTION__, ##__VA_ARGS__) class BacktraceImpl { public: virtual ~BacktraceImpl() { } Loading
libbacktrace/BacktraceThread.cpp +55 −51 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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; Loading @@ -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); } } Loading Loading @@ -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; } Loading @@ -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; } } Loading @@ -202,7 +199,10 @@ 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; if (pthread_mutex_lock(&g_sigaction_mutex) == 0) { struct sigaction act, oldact; memset(&act, 0, sizeof(act)); act.sa_sigaction = SignalHandler; Loading @@ -212,7 +212,11 @@ bool BacktraceThread::Unwind(size_t num_ignore_frames) { retval = TriggerUnwindOnThread(entry); sigaction(SIGURG, &oldact, NULL); } else { ALOGW("%s::%s(): sigaction failed %s\n", __FILE__, __FUNCTION__, strerror(errno)); BACK_LOGW("sigaction failed %s", strerror(errno)); } pthread_mutex_unlock(&g_sigaction_mutex); } else { BACK_LOGW("unable to acquire sigaction mutex."); } if (retval) { Loading
libbacktrace/BacktraceThread.h +9 −10 Original line number Diff line number Diff line Loading @@ -32,26 +32,25 @@ typedef enum { class BacktraceThreadInterface; class ThreadEntry { public: struct ThreadEntry { ThreadEntry( BacktraceThreadInterface* impl, pid_t pid, pid_t tid, size_t num_ignore_frames); ~ThreadEntry(); bool Match(pid_t pid, pid_t tid) { return (pid == pid_ && tid == tid_); } bool Match(pid_t chk_pid, pid_t chk_tid) { return (chk_pid == pid && chk_tid == tid); } static ThreadEntry* AddThreadToUnwind( BacktraceThreadInterface* thread_intf, pid_t pid, pid_t tid, size_t num_ignored_frames); BacktraceThreadInterface* thread_intf_; pid_t pid_; pid_t tid_; ThreadEntry* next_; ThreadEntry* prev_; int32_t state_; int num_ignore_frames_; BacktraceThreadInterface* thread_intf; pid_t pid; pid_t tid; ThreadEntry* next; ThreadEntry* prev; int32_t state; int num_ignore_frames; }; // Interface class that does not contain any local storage, only defines Loading