Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 10ab87f6 authored by Christopher Ferris's avatar Christopher Ferris
Browse files

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
parent c1b3c8ef
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -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());