From 10ab87f646cb1e21ab102632e53705399860a04d Mon Sep 17 00:00:00 2001 From: Christopher Ferris Date: Thu, 9 Mar 2017 14:04:43 -0800 Subject: [PATCH] Restore errno in signal handlers. There was a problem where errno could be set in a signal handler and cause bugs if other system calls were interrupted. There isn't strong evidence this is causing any issues, but add this proactively. Bug: 31448909 Test: Ran the backtrace unit tests, backtraces few random processes, Test: forced the ANR path for some zygote based processes. Test: Ran the art ThreadStress test a few times. Change-Id: I5abc9e330a5e86cea7015e2362f66044c6bc37d0 --- libbacktrace/BacktraceCurrent.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/libbacktrace/BacktraceCurrent.cpp b/libbacktrace/BacktraceCurrent.cpp index 5173e2cc9..d7a3b011e 100644 --- a/libbacktrace/BacktraceCurrent.cpp +++ b/libbacktrace/BacktraceCurrent.cpp @@ -95,11 +95,31 @@ bool BacktraceCurrent::DiscardFrame(const backtrace_frame_data_t& frame) { static pthread_mutex_t g_sigaction_mutex = PTHREAD_MUTEX_INITIALIZER; +// Since errno is stored per thread, changing it in the signal handler +// modifies the value on the thread in which the signal handler executes. +// If a signal occurs between a call and an errno check, it's possible +// to get the errno set here. Always save and restore it just in case +// code would modify it. +class ErrnoRestorer { + public: + ErrnoRestorer() : saved_errno_(errno) {} + ~ErrnoRestorer() { + errno = saved_errno_; + } + + private: + int saved_errno_; +}; + 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); } static void SignalHandler(int, siginfo_t*, void* sigcontext) { + ErrnoRestorer restore; + ThreadEntry* entry = ThreadEntry::Get(getpid(), gettid(), false); if (!entry) { BACK_LOGE("pid %d, tid %d entry not found", getpid(), gettid());