diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp index 285aa6edf..7dd9227b3 100644 --- a/libbacktrace/Android.bp +++ b/libbacktrace/Android.bp @@ -110,7 +110,7 @@ cc_library { "libunwind", ], - static_libs: ["libcutils"], + static_libs: ["libasync_safe", "libcutils"], }, }, } diff --git a/libbacktrace/BacktraceAsyncSafeLog.h b/libbacktrace/BacktraceAsyncSafeLog.h new file mode 100644 index 000000000..14f51be24 --- /dev/null +++ b/libbacktrace/BacktraceAsyncSafeLog.h @@ -0,0 +1,41 @@ +/* + * 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 + +// 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 diff --git a/libbacktrace/BacktraceCurrent.cpp b/libbacktrace/BacktraceCurrent.cpp index d7a3b011e..fb76b858d 100644 --- a/libbacktrace/BacktraceCurrent.cpp +++ b/libbacktrace/BacktraceCurrent.cpp @@ -31,8 +31,8 @@ #include #include +#include "BacktraceAsyncSafeLog.h" #include "BacktraceCurrent.h" -#include "BacktraceLog.h" #include "ThreadEntry.h" #include "thread_utils.h" @@ -47,7 +47,7 @@ bool BacktraceCurrent::ReadWord(uintptr_t ptr, word_t* out_value) { *out_value = *reinterpret_cast(ptr); return true; } else { - BACK_LOGW("pointer %p not in a readable map", reinterpret_cast(ptr)); + BACK_ASYNC_SAFE_LOGW("pointer %p not in a readable map", reinterpret_cast(ptr)); *out_value = static_cast(-1); return false; } @@ -114,7 +114,8 @@ class ErrnoRestorer { static void SignalLogOnly(int, siginfo_t*, void*) { 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) { @@ -122,7 +123,7 @@ static void SignalHandler(int, siginfo_t*, void* sigcontext) { ThreadEntry* entry = ThreadEntry::Get(getpid(), gettid(), false); 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; } @@ -141,7 +142,7 @@ static void SignalHandler(int, siginfo_t*, void* sigcontext) { entry->Wake(); } else { // 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."); } } @@ -159,7 +160,7 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) { act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; sigemptyset(&act.sa_mask); 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); pthread_mutex_unlock(&g_sigaction_mutex); error_ = BACKTRACE_UNWIND_ERROR_INTERNAL; @@ -212,7 +213,7 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) { // Wait for the thread to indicate it is done with the ThreadEntry. if (!entry->Wait(3)) { // 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 { // Check to see if the thread has disappeared. @@ -220,7 +221,7 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) { 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."); + BACK_ASYNC_SAFE_LOGE("Timed out waiting for signal handler to get ucontext data."); } } diff --git a/libbacktrace/ThreadEntry.cpp b/libbacktrace/ThreadEntry.cpp index 084c1aa91..9bd59e4a2 100644 --- a/libbacktrace/ThreadEntry.cpp +++ b/libbacktrace/ThreadEntry.cpp @@ -21,7 +21,7 @@ #include #include -#include "BacktraceLog.h" +#include "BacktraceAsyncSafeLog.h" #include "ThreadEntry.h" // Initialize static member variables. @@ -106,7 +106,7 @@ bool ThreadEntry::Wait(int value) { while (wait_value_ != value) { int ret = pthread_cond_timedwait(&wait_cond_, &wait_mutex_, &ts); 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; break; }