diff --git a/compiler-rt/lib/asan/asan_internal.h b/compiler-rt/lib/asan/asan_internal.h index 713f17c06af3..041fa3dce803 100644 --- a/compiler-rt/lib/asan/asan_internal.h +++ b/compiler-rt/lib/asan/asan_internal.h @@ -129,7 +129,7 @@ uintptr_t GetThreadSelf(); int AtomicInc(int *a); // Wrapper for TLS/TSD. -void AsanTSDInit(); +void AsanTSDInit(void (*destructor)(void *tsd)); void *AsanTSDGet(); void AsanTSDSet(void *tsd); diff --git a/compiler-rt/lib/asan/asan_posix.cc b/compiler-rt/lib/asan/asan_posix.cc index 2d48a19613c5..76d5876e7148 100644 --- a/compiler-rt/lib/asan/asan_posix.cc +++ b/compiler-rt/lib/asan/asan_posix.cc @@ -97,10 +97,10 @@ int AtomicInc(int *a) { static pthread_key_t tsd_key; static bool tsd_key_inited = false; -void AsanTSDInit() { +void AsanTSDInit(void (*destructor)(void *tsd)) { CHECK(!tsd_key_inited); tsd_key_inited = true; - CHECK(0 == pthread_key_create(&tsd_key, 0)); + CHECK(0 == pthread_key_create(&tsd_key, destructor)); } void *AsanTSDGet() { diff --git a/compiler-rt/lib/asan/asan_thread.cc b/compiler-rt/lib/asan/asan_thread.cc index 66bb01e23a6e..6e6436b81449 100644 --- a/compiler-rt/lib/asan/asan_thread.cc +++ b/compiler-rt/lib/asan/asan_thread.cc @@ -40,7 +40,23 @@ AsanThread *AsanThread::Create(int parent_tid, void *(*start_routine) (void *), return thread; } +void AsanThreadSummary::TSDDtor(void *tsd) { + AsanThreadSummary *summary = (AsanThreadSummary*)tsd; + if (FLAG_v >= 1) { + Report("T%d TSDDtor\n", summary->tid()); + } + if (summary->thread()) { + summary->thread()->Destroy(); + } +} + void AsanThread::Destroy() { + if (FLAG_v >= 1) { + Report("T%d exited\n", tid()); + } + + asanThreadRegistry().UnregisterThread(this); + CHECK(summary()->thread() == NULL); // We also clear the shadow on thread destruction because // some code may still be executing in later TSD destructors // and we don't want it to have any poisoned stack. @@ -78,11 +94,6 @@ void *AsanThread::ThreadStart() { void *res = start_routine_(arg_); malloc_storage().CommitBack(); - if (FLAG_v >= 1) { - Report("T%d exited\n", tid()); - } - - asanThreadRegistry().UnregisterThread(this); this->Destroy(); return res; diff --git a/compiler-rt/lib/asan/asan_thread.h b/compiler-rt/lib/asan/asan_thread.h index 45351a7a7af2..9fc1e26ca6b8 100644 --- a/compiler-rt/lib/asan/asan_thread.h +++ b/compiler-rt/lib/asan/asan_thread.h @@ -51,6 +51,8 @@ class AsanThreadSummary { void set_tid(int tid) { tid_ = tid; } AsanThread *thread() { return thread_; } void set_thread(AsanThread *thread) { thread_ = thread; } + static void TSDDtor(void *tsd); + private: int tid_; int parent_tid_; diff --git a/compiler-rt/lib/asan/asan_thread_registry.cc b/compiler-rt/lib/asan/asan_thread_registry.cc index c905201d0a30..cd48769aa5b7 100644 --- a/compiler-rt/lib/asan/asan_thread_registry.cc +++ b/compiler-rt/lib/asan/asan_thread_registry.cc @@ -32,7 +32,7 @@ AsanThreadRegistry::AsanThreadRegistry(LinkerInitialized x) mu_(x) { } void AsanThreadRegistry::Init() { - AsanTSDInit(); + AsanTSDInit(AsanThreadSummary::TSDDtor); main_thread_.set_summary(&main_thread_summary_); main_thread_summary_.set_thread(&main_thread_); RegisterThread(&main_thread_); diff --git a/compiler-rt/lib/asan/tests/asan_test.cc b/compiler-rt/lib/asan/tests/asan_test.cc index 0201290ee677..60c554cf19e5 100644 --- a/compiler-rt/lib/asan/tests/asan_test.cc +++ b/compiler-rt/lib/asan/tests/asan_test.cc @@ -1637,6 +1637,18 @@ TEST(AddressSanitizer, ThreadedStressStackReuseTest) { } } +static void *PthreadExit(void *a) { + pthread_exit(0); +} + +TEST(AddressSanitizer, PthreadExitTest) { + pthread_t t; + for (int i = 0; i < 1000; i++) { + pthread_create(&t, 0, PthreadExit, 0); + pthread_join(t, 0); + } +} + #ifdef __EXCEPTIONS __attribute__((noinline)) static void StackReuseAndException() {