summaryrefslogtreecommitdiffstats
path: root/libbacktrace
diff options
context:
space:
mode:
authorChristopher Ferris <cferris@google.com>2017-03-09 14:04:43 -0800
committerChristopher Ferris <cferris@google.com>2017-03-10 10:13:48 -0800
commit10ab87f646cb1e21ab102632e53705399860a04d (patch)
treeaf86aa4f16a5f26abaa40dd40f63e6be98cc3cc7 /libbacktrace
parentc1b3c8ef2629eac2a73aa4a95bf43a66edf4cd0f (diff)
downloadsystem_core-10ab87f646cb1e21ab102632e53705399860a04d.tar.gz
system_core-10ab87f646cb1e21ab102632e53705399860a04d.tar.bz2
system_core-10ab87f646cb1e21ab102632e53705399860a04d.zip
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
Diffstat (limited to 'libbacktrace')
-rw-r--r--libbacktrace/BacktraceCurrent.cpp20
1 files changed, 20 insertions, 0 deletions
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());