[asan] make sure the AsanThread object is destroyed if pthread_exit is called
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@149940 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/asan/asan_internal.h b/lib/asan/asan_internal.h
index 713f17c..041fa3d 100644
--- a/lib/asan/asan_internal.h
+++ b/lib/asan/asan_internal.h
@@ -129,7 +129,7 @@
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/lib/asan/asan_posix.cc b/lib/asan/asan_posix.cc
index 2d48a19..76d5876 100644
--- a/lib/asan/asan_posix.cc
+++ b/lib/asan/asan_posix.cc
@@ -97,10 +97,10 @@
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/lib/asan/asan_thread.cc b/lib/asan/asan_thread.cc
index 66bb01e..6e6436b 100644
--- a/lib/asan/asan_thread.cc
+++ b/lib/asan/asan_thread.cc
@@ -40,7 +40,23 @@
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 *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/lib/asan/asan_thread.h b/lib/asan/asan_thread.h
index 45351a7..9fc1e26 100644
--- a/lib/asan/asan_thread.h
+++ b/lib/asan/asan_thread.h
@@ -51,6 +51,8 @@
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/lib/asan/asan_thread_registry.cc b/lib/asan/asan_thread_registry.cc
index c905201..cd48769 100644
--- a/lib/asan/asan_thread_registry.cc
+++ b/lib/asan/asan_thread_registry.cc
@@ -32,7 +32,7 @@
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/lib/asan/tests/asan_test.cc b/lib/asan/tests/asan_test.cc
index 0201290..60c554c 100644
--- a/lib/asan/tests/asan_test.cc
+++ b/lib/asan/tests/asan_test.cc
@@ -1637,6 +1637,18 @@
}
}
+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() {