Loading libbacktrace/Android.bp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -110,7 +110,7 @@ cc_library { "libunwind", "libunwind", ], ], static_libs: ["libcutils"], static_libs: ["libasync_safe", "libcutils"], }, }, }, }, } } Loading libbacktrace/BacktraceAsyncSafeLog.h 0 → 100644 +41 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _LIBBACKTRACE_BACKTRACE_ASYNC_SAFE_LOG_H #define _LIBBACKTRACE_BACKTRACE_ASYNC_SAFE_LOG_H #if defined(__ANDROID__) #include <async_safe/log.h> // Logging macros for use in signal handler, only available on target. #define BACK_ASYNC_SAFE_LOGW(format, ...) \ async_safe_format_log(ANDROID_LOG_WARN, "libbacktrace", "%s: " format, __PRETTY_FUNCTION__, \ ##__VA_ARGS__) #define BACK_ASYNC_SAFE_LOGE(format, ...) \ async_safe_format_log(ANDROID_LOG_ERROR, "libbacktrace", "%s: " format, __PRETTY_FUNCTION__, \ ##__VA_ARGS__) #else #define BACK_ASYNC_SAFE_LOGW(format, ...) #define BACK_ASYNC_SAFE_LOGE(format, ...) #endif #endif // _LIBBACKTRACE_BACKTRACE_ASYNC_SAFE_LOG_H libbacktrace/BacktraceCurrent.cpp +9 −8 Original line number Original line Diff line number Diff line Loading @@ -31,8 +31,8 @@ #include <backtrace/Backtrace.h> #include <backtrace/Backtrace.h> #include <backtrace/BacktraceMap.h> #include <backtrace/BacktraceMap.h> #include "BacktraceAsyncSafeLog.h" #include "BacktraceCurrent.h" #include "BacktraceCurrent.h" #include "BacktraceLog.h" #include "ThreadEntry.h" #include "ThreadEntry.h" #include "thread_utils.h" #include "thread_utils.h" Loading @@ -47,7 +47,7 @@ bool BacktraceCurrent::ReadWord(uintptr_t ptr, word_t* out_value) { *out_value = *reinterpret_cast<word_t*>(ptr); *out_value = *reinterpret_cast<word_t*>(ptr); return true; return true; } else { } else { BACK_LOGW("pointer %p not in a readable map", reinterpret_cast<void*>(ptr)); BACK_ASYNC_SAFE_LOGW("pointer %p not in a readable map", reinterpret_cast<void*>(ptr)); *out_value = static_cast<word_t>(-1); *out_value = static_cast<word_t>(-1); return false; return false; } } Loading Loading @@ -114,7 +114,8 @@ class ErrnoRestorer { static void SignalLogOnly(int, siginfo_t*, void*) { static void SignalLogOnly(int, siginfo_t*, void*) { ErrnoRestorer restore; ErrnoRestorer restore; BACK_LOGE("pid %d, tid %d: Received a spurious signal %d\n", getpid(), gettid(), THREAD_SIGNAL); BACK_ASYNC_SAFE_LOGE("pid %d, tid %d: Received a spurious signal %d\n", getpid(), gettid(), THREAD_SIGNAL); } } static void SignalHandler(int, siginfo_t*, void* sigcontext) { static void SignalHandler(int, siginfo_t*, void* sigcontext) { Loading @@ -122,7 +123,7 @@ static void SignalHandler(int, siginfo_t*, void* sigcontext) { ThreadEntry* entry = ThreadEntry::Get(getpid(), gettid(), false); ThreadEntry* entry = ThreadEntry::Get(getpid(), gettid(), false); if (!entry) { if (!entry) { BACK_LOGE("pid %d, tid %d entry not found", getpid(), gettid()); BACK_ASYNC_SAFE_LOGE("pid %d, tid %d entry not found", getpid(), gettid()); return; return; } } Loading @@ -141,7 +142,7 @@ static void SignalHandler(int, siginfo_t*, void* sigcontext) { entry->Wake(); entry->Wake(); } else { } else { // At this point, it is possible that entry has been freed, so just exit. // At this point, it is possible that entry has been freed, so just exit. BACK_LOGE("Timed out waiting for unwind thread to indicate it completed."); BACK_ASYNC_SAFE_LOGE("Timed out waiting for unwind thread to indicate it completed."); } } } } Loading @@ -159,7 +160,7 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) { act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; sigemptyset(&act.sa_mask); sigemptyset(&act.sa_mask); if (sigaction(THREAD_SIGNAL, &act, &oldact) != 0) { if (sigaction(THREAD_SIGNAL, &act, &oldact) != 0) { BACK_LOGE("sigaction failed: %s", strerror(errno)); BACK_ASYNC_SAFE_LOGE("sigaction failed: %s", strerror(errno)); ThreadEntry::Remove(entry); ThreadEntry::Remove(entry); pthread_mutex_unlock(&g_sigaction_mutex); pthread_mutex_unlock(&g_sigaction_mutex); error_ = BACKTRACE_UNWIND_ERROR_INTERNAL; error_ = BACKTRACE_UNWIND_ERROR_INTERNAL; Loading Loading @@ -212,7 +213,7 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) { // Wait for the thread to indicate it is done with the ThreadEntry. // Wait for the thread to indicate it is done with the ThreadEntry. if (!entry->Wait(3)) { if (!entry->Wait(3)) { // Send a warning, but do not mark as a failure to unwind. // Send a warning, but do not mark as a failure to unwind. BACK_LOGW("Timed out waiting for signal handler to indicate it finished."); BACK_ASYNC_SAFE_LOGW("Timed out waiting for signal handler to indicate it finished."); } } } else { } else { // Check to see if the thread has disappeared. // Check to see if the thread has disappeared. Loading @@ -220,7 +221,7 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) { error_ = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST; error_ = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST; } else { } else { error_ = BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT; error_ = BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT; BACK_LOGE("Timed out waiting for signal handler to get ucontext data."); BACK_ASYNC_SAFE_LOGE("Timed out waiting for signal handler to get ucontext data."); } } } } Loading libbacktrace/ThreadEntry.cpp +2 −2 Original line number Original line Diff line number Diff line Loading @@ -21,7 +21,7 @@ #include <time.h> #include <time.h> #include <ucontext.h> #include <ucontext.h> #include "BacktraceLog.h" #include "BacktraceAsyncSafeLog.h" #include "ThreadEntry.h" #include "ThreadEntry.h" // Initialize static member variables. // Initialize static member variables. Loading Loading @@ -106,7 +106,7 @@ bool ThreadEntry::Wait(int value) { while (wait_value_ != value) { while (wait_value_ != value) { int ret = pthread_cond_timedwait(&wait_cond_, &wait_mutex_, &ts); int ret = pthread_cond_timedwait(&wait_cond_, &wait_mutex_, &ts); if (ret != 0) { if (ret != 0) { BACK_LOGW("pthread_cond_timedwait for value %d failed: %s", value, strerror(ret)); BACK_ASYNC_SAFE_LOGW("pthread_cond_timedwait for value %d failed: %s", value, strerror(ret)); wait_completed = false; wait_completed = false; break; break; } } Loading Loading
libbacktrace/Android.bp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -110,7 +110,7 @@ cc_library { "libunwind", "libunwind", ], ], static_libs: ["libcutils"], static_libs: ["libasync_safe", "libcutils"], }, }, }, }, } } Loading
libbacktrace/BacktraceAsyncSafeLog.h 0 → 100644 +41 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _LIBBACKTRACE_BACKTRACE_ASYNC_SAFE_LOG_H #define _LIBBACKTRACE_BACKTRACE_ASYNC_SAFE_LOG_H #if defined(__ANDROID__) #include <async_safe/log.h> // Logging macros for use in signal handler, only available on target. #define BACK_ASYNC_SAFE_LOGW(format, ...) \ async_safe_format_log(ANDROID_LOG_WARN, "libbacktrace", "%s: " format, __PRETTY_FUNCTION__, \ ##__VA_ARGS__) #define BACK_ASYNC_SAFE_LOGE(format, ...) \ async_safe_format_log(ANDROID_LOG_ERROR, "libbacktrace", "%s: " format, __PRETTY_FUNCTION__, \ ##__VA_ARGS__) #else #define BACK_ASYNC_SAFE_LOGW(format, ...) #define BACK_ASYNC_SAFE_LOGE(format, ...) #endif #endif // _LIBBACKTRACE_BACKTRACE_ASYNC_SAFE_LOG_H
libbacktrace/BacktraceCurrent.cpp +9 −8 Original line number Original line Diff line number Diff line Loading @@ -31,8 +31,8 @@ #include <backtrace/Backtrace.h> #include <backtrace/Backtrace.h> #include <backtrace/BacktraceMap.h> #include <backtrace/BacktraceMap.h> #include "BacktraceAsyncSafeLog.h" #include "BacktraceCurrent.h" #include "BacktraceCurrent.h" #include "BacktraceLog.h" #include "ThreadEntry.h" #include "ThreadEntry.h" #include "thread_utils.h" #include "thread_utils.h" Loading @@ -47,7 +47,7 @@ bool BacktraceCurrent::ReadWord(uintptr_t ptr, word_t* out_value) { *out_value = *reinterpret_cast<word_t*>(ptr); *out_value = *reinterpret_cast<word_t*>(ptr); return true; return true; } else { } else { BACK_LOGW("pointer %p not in a readable map", reinterpret_cast<void*>(ptr)); BACK_ASYNC_SAFE_LOGW("pointer %p not in a readable map", reinterpret_cast<void*>(ptr)); *out_value = static_cast<word_t>(-1); *out_value = static_cast<word_t>(-1); return false; return false; } } Loading Loading @@ -114,7 +114,8 @@ class ErrnoRestorer { static void SignalLogOnly(int, siginfo_t*, void*) { static void SignalLogOnly(int, siginfo_t*, void*) { ErrnoRestorer restore; ErrnoRestorer restore; BACK_LOGE("pid %d, tid %d: Received a spurious signal %d\n", getpid(), gettid(), THREAD_SIGNAL); BACK_ASYNC_SAFE_LOGE("pid %d, tid %d: Received a spurious signal %d\n", getpid(), gettid(), THREAD_SIGNAL); } } static void SignalHandler(int, siginfo_t*, void* sigcontext) { static void SignalHandler(int, siginfo_t*, void* sigcontext) { Loading @@ -122,7 +123,7 @@ static void SignalHandler(int, siginfo_t*, void* sigcontext) { ThreadEntry* entry = ThreadEntry::Get(getpid(), gettid(), false); ThreadEntry* entry = ThreadEntry::Get(getpid(), gettid(), false); if (!entry) { if (!entry) { BACK_LOGE("pid %d, tid %d entry not found", getpid(), gettid()); BACK_ASYNC_SAFE_LOGE("pid %d, tid %d entry not found", getpid(), gettid()); return; return; } } Loading @@ -141,7 +142,7 @@ static void SignalHandler(int, siginfo_t*, void* sigcontext) { entry->Wake(); entry->Wake(); } else { } else { // At this point, it is possible that entry has been freed, so just exit. // At this point, it is possible that entry has been freed, so just exit. BACK_LOGE("Timed out waiting for unwind thread to indicate it completed."); BACK_ASYNC_SAFE_LOGE("Timed out waiting for unwind thread to indicate it completed."); } } } } Loading @@ -159,7 +160,7 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) { act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; sigemptyset(&act.sa_mask); sigemptyset(&act.sa_mask); if (sigaction(THREAD_SIGNAL, &act, &oldact) != 0) { if (sigaction(THREAD_SIGNAL, &act, &oldact) != 0) { BACK_LOGE("sigaction failed: %s", strerror(errno)); BACK_ASYNC_SAFE_LOGE("sigaction failed: %s", strerror(errno)); ThreadEntry::Remove(entry); ThreadEntry::Remove(entry); pthread_mutex_unlock(&g_sigaction_mutex); pthread_mutex_unlock(&g_sigaction_mutex); error_ = BACKTRACE_UNWIND_ERROR_INTERNAL; error_ = BACKTRACE_UNWIND_ERROR_INTERNAL; Loading Loading @@ -212,7 +213,7 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) { // Wait for the thread to indicate it is done with the ThreadEntry. // Wait for the thread to indicate it is done with the ThreadEntry. if (!entry->Wait(3)) { if (!entry->Wait(3)) { // Send a warning, but do not mark as a failure to unwind. // Send a warning, but do not mark as a failure to unwind. BACK_LOGW("Timed out waiting for signal handler to indicate it finished."); BACK_ASYNC_SAFE_LOGW("Timed out waiting for signal handler to indicate it finished."); } } } else { } else { // Check to see if the thread has disappeared. // Check to see if the thread has disappeared. Loading @@ -220,7 +221,7 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) { error_ = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST; error_ = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST; } else { } else { error_ = BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT; error_ = BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT; BACK_LOGE("Timed out waiting for signal handler to get ucontext data."); BACK_ASYNC_SAFE_LOGE("Timed out waiting for signal handler to get ucontext data."); } } } } Loading
libbacktrace/ThreadEntry.cpp +2 −2 Original line number Original line Diff line number Diff line Loading @@ -21,7 +21,7 @@ #include <time.h> #include <time.h> #include <ucontext.h> #include <ucontext.h> #include "BacktraceLog.h" #include "BacktraceAsyncSafeLog.h" #include "ThreadEntry.h" #include "ThreadEntry.h" // Initialize static member variables. // Initialize static member variables. Loading Loading @@ -106,7 +106,7 @@ bool ThreadEntry::Wait(int value) { while (wait_value_ != value) { while (wait_value_ != value) { int ret = pthread_cond_timedwait(&wait_cond_, &wait_mutex_, &ts); int ret = pthread_cond_timedwait(&wait_cond_, &wait_mutex_, &ts); if (ret != 0) { if (ret != 0) { BACK_LOGW("pthread_cond_timedwait for value %d failed: %s", value, strerror(ret)); BACK_ASYNC_SAFE_LOGW("pthread_cond_timedwait for value %d failed: %s", value, strerror(ret)); wait_completed = false; wait_completed = false; break; break; } } Loading