diff options
5 files changed, 37 insertions, 12 deletions
diff --git a/compiler-rt/lib/lsan/lsan_common.cc b/compiler-rt/lib/lsan/lsan_common.cc index 5ae3ad27ef8..ade8b0a02f1 100644 --- a/compiler-rt/lib/lsan/lsan_common.cc +++ b/compiler-rt/lib/lsan/lsan_common.cc @@ -201,11 +201,13 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads,        continue;      }      uptr sp; -    bool have_registers = -        (suspended_threads.GetRegistersAndSP(i, registers.data(), &sp) == 0); -    if (!have_registers) { -      Report("Unable to get registers from thread %d.\n"); -      // If unable to get SP, consider the entire stack to be reachable. +    PtraceRegistersStatus have_registers = +        suspended_threads.GetRegistersAndSP(i, registers.data(), &sp); +    if (have_registers != REGISTERS_AVAILABLE) { +      Report("Unable to get registers from thread %d.\n", os_id); +      // If unable to get SP, consider the entire stack to be reachable unless +      // GetRegistersAndSP failed with ESRCH. +      if (have_registers == REGISTERS_UNAVAILABLE_FATAL) continue;        sp = stack_begin;      } @@ -253,7 +255,7 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads,          if (tls_end > cache_end)            ScanRangeForPointers(cache_end, tls_end, frontier, "TLS", kReachable);        } -      if (dtls) { +      if (dtls && !DTLSInDestruction(dtls)) {          for (uptr j = 0; j < dtls->dtv_size; ++j) {            uptr dtls_beg = dtls->dtv[j].beg;            uptr dtls_end = dtls_beg + dtls->dtv[j].size; @@ -263,6 +265,10 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads,                                   kReachable);            }          } +      } else { +        // We are handling a thread with DTLS under destruction. Log about +        // this and continue. +        LOG_THREADS("Thread %d has DTLS under destruction.\n", os_id);        }      }    } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld.h b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld.h index aa6f5d833a4..41752d8f66e 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld.h @@ -20,6 +20,12 @@  namespace __sanitizer {  typedef int SuspendedThreadID; +enum PtraceRegistersStatus { +  REGISTERS_UNAVAILABLE_FATAL = -1, +  REGISTERS_UNAVAILABLE = 0, +  REGISTERS_AVAILABLE = 1 +}; +  // Holds the list of suspended threads and provides an interface to dump their  // register contexts.  class SuspendedThreadsList { @@ -30,7 +36,8 @@ class SuspendedThreadsList {      CHECK_LT(index, thread_ids_.size());      return thread_ids_[index];    } -  int GetRegistersAndSP(uptr index, uptr *buffer, uptr *sp) const; +  PtraceRegistersStatus GetRegistersAndSP(uptr index, uptr *buffer, +                                          uptr *sp) const;    // The buffer in GetRegistersAndSP should be at least this big.    static uptr RegisterCount();    uptr thread_count() const { return thread_ids_.size(); } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc index ce8873b9e8c..3c0fd7b1352 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc @@ -493,9 +493,9 @@ typedef _user_regs_struct regs_struct;  #error "Unsupported architecture"  #endif // SANITIZER_ANDROID && defined(__arm__) -int SuspendedThreadsList::GetRegistersAndSP(uptr index, -                                            uptr *buffer, -                                            uptr *sp) const { +PtraceRegistersStatus SuspendedThreadsList::GetRegistersAndSP(uptr index, +                                                              uptr *buffer, +                                                              uptr *sp) const {    pid_t tid = GetThreadID(index);    regs_struct regs;    int pterrno; @@ -513,12 +513,16 @@ int SuspendedThreadsList::GetRegistersAndSP(uptr index,    if (isErr) {      VReport(1, "Could not get registers from thread %d (errno %d).\n", tid,              pterrno); -    return -1; +    // ESRCH means that the given thread is not suspended or already dead. +    // Therefore it's unsafe to inspect its data (e.g. walk through stack) and +    // we should notify caller about this. +    return pterrno == ESRCH ? REGISTERS_UNAVAILABLE_FATAL +                            : REGISTERS_UNAVAILABLE;    }    *sp = regs.REG_SP;    internal_memcpy(buffer, ®s, sizeof(regs)); -  return 0; +  return REGISTERS_AVAILABLE;  }  uptr SuspendedThreadsList::RegisterCount() { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cc b/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cc index 77c1947d52d..aa146d01f92 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cc @@ -136,11 +136,17 @@ void DTLS_on_libc_memalign(void *ptr, uptr size) {  DTLS *DTLS_Get() { return &dtls; } +bool DTLSInDestruction(DTLS *dtls) { +  return dtls->dtv_size == kDestroyedThread; +} +  #else  void DTLS_on_libc_memalign(void *ptr, uptr size) {}  DTLS::DTV *DTLS_on_tls_get_addr(void *arg, void *res) { return 0; }  DTLS *DTLS_Get() { return 0; }  void DTLS_Destroy() {} +bool DTLSInDestruction(DTLS *dtls) { UNREACHABLE(); } +  #endif  // SANITIZER_INTERCEPT_TLS_GET_ADDR  }  // namespace __sanitizer diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.h b/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.h index 58d47634d38..199a3b2e9c6 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.h @@ -55,6 +55,8 @@ DTLS::DTV *DTLS_on_tls_get_addr(void *arg, void *res, uptr static_tls_begin,  void DTLS_on_libc_memalign(void *ptr, uptr size);  DTLS *DTLS_Get();  void DTLS_Destroy();  // Make sure to call this before the thread is destroyed. +// Returns true if DTLS of suspended thread is in destruction process. +bool DTLSInDestruction(DTLS *dtls);  }  // namespace __sanitizer  | 

