Index: lib/lsan/lsan_common.cc =================================================================== --- lib/lsan/lsan_common.cc +++ lib/lsan/lsan_common.cc @@ -204,9 +204,15 @@ 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. - sp = stack_begin; + Report("Unable to get registers from thread %d.\n", os_id); + // If unable to get SP, consider the entire stack to be reachable + // depending on consider_entire_stack_reachable flag. We cannot do this + // unconditionally because stack memory can be already unmapped at this + // point. + if (flags()->consider_entire_stack_reachable) + sp = stack_begin; + else + continue; } if (flags()->use_registers && have_registers) @@ -253,7 +259,7 @@ 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 +269,10 @@ 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); } } } Index: lib/lsan/lsan_flags.inc =================================================================== --- lib/lsan/lsan_flags.inc +++ lib/lsan/lsan_flags.inc @@ -45,3 +45,6 @@ LSAN_FLAG(bool, log_pointers, false, "Debug logging") LSAN_FLAG(bool, log_threads, false, "Debug logging") LSAN_FLAG(const char *, suppressions, "", "Suppressions file name.") +LSAN_FLAG(bool, consider_entire_stack_reachable, true, + "Consider entire stack to be reachable if we unable to retrive SP " + "from suspended thread.") Index: lib/sanitizer_common/sanitizer_tls_get_addr.h =================================================================== --- lib/sanitizer_common/sanitizer_tls_get_addr.h +++ lib/sanitizer_common/sanitizer_tls_get_addr.h @@ -55,6 +55,8 @@ 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 Index: lib/sanitizer_common/sanitizer_tls_get_addr.cc =================================================================== --- lib/sanitizer_common/sanitizer_tls_get_addr.cc +++ lib/sanitizer_common/sanitizer_tls_get_addr.cc @@ -136,11 +136,17 @@ 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