Use async safe logging in signal handlers.

Test: Boot on bullhead.
Test: Ran the libbacktrace tests on bullhead.
Test: Added a temporary log message in the signal handler, and ran the
Test: backtrace tests.
Change-Id: I0a6888c9f311af2c8cc7fbb4929315911bd2bb3c
This commit is contained in:
Christopher Ferris 2017-05-03 17:22:24 -07:00
parent 8fad110bfa
commit f30a810bce
4 changed files with 53 additions and 11 deletions

View file

@ -110,7 +110,7 @@ cc_library {
"libunwind",
],
static_libs: ["libcutils"],
static_libs: ["libasync_safe", "libcutils"],
},
},
}

View file

@ -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 <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

View file

@ -31,8 +31,8 @@
#include <backtrace/Backtrace.h>
#include <backtrace/BacktraceMap.h>
#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<word_t*>(ptr);
return true;
} 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);
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.");
}
}

View file

@ -21,7 +21,7 @@
#include <time.h>
#include <ucontext.h>
#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;
}