[asan] make sure the AsanThread object is destroyed if pthread_exit is called

llvm-svn: 149940
This commit is contained in:
Kostya Serebryany 2012-02-07 00:27:15 +00:00
parent a2bbac3ffc
commit b5eb5a7a05
6 changed files with 34 additions and 9 deletions

View File

@ -129,7 +129,7 @@ uintptr_t GetThreadSelf();
int AtomicInc(int *a); int AtomicInc(int *a);
// Wrapper for TLS/TSD. // Wrapper for TLS/TSD.
void AsanTSDInit(); void AsanTSDInit(void (*destructor)(void *tsd));
void *AsanTSDGet(); void *AsanTSDGet();
void AsanTSDSet(void *tsd); void AsanTSDSet(void *tsd);

View File

@ -97,10 +97,10 @@ int AtomicInc(int *a) {
static pthread_key_t tsd_key; static pthread_key_t tsd_key;
static bool tsd_key_inited = false; static bool tsd_key_inited = false;
void AsanTSDInit() { void AsanTSDInit(void (*destructor)(void *tsd)) {
CHECK(!tsd_key_inited); CHECK(!tsd_key_inited);
tsd_key_inited = true; tsd_key_inited = true;
CHECK(0 == pthread_key_create(&tsd_key, 0)); CHECK(0 == pthread_key_create(&tsd_key, destructor));
} }
void *AsanTSDGet() { void *AsanTSDGet() {

View File

@ -40,7 +40,23 @@ AsanThread *AsanThread::Create(int parent_tid, void *(*start_routine) (void *),
return thread; 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() { 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 // We also clear the shadow on thread destruction because
// some code may still be executing in later TSD destructors // some code may still be executing in later TSD destructors
// and we don't want it to have any poisoned stack. // and we don't want it to have any poisoned stack.
@ -78,11 +94,6 @@ void *AsanThread::ThreadStart() {
void *res = start_routine_(arg_); void *res = start_routine_(arg_);
malloc_storage().CommitBack(); malloc_storage().CommitBack();
if (FLAG_v >= 1) {
Report("T%d exited\n", tid());
}
asanThreadRegistry().UnregisterThread(this);
this->Destroy(); this->Destroy();
return res; return res;

View File

@ -51,6 +51,8 @@ class AsanThreadSummary {
void set_tid(int tid) { tid_ = tid; } void set_tid(int tid) { tid_ = tid; }
AsanThread *thread() { return thread_; } AsanThread *thread() { return thread_; }
void set_thread(AsanThread *thread) { thread_ = thread; } void set_thread(AsanThread *thread) { thread_ = thread; }
static void TSDDtor(void *tsd);
private: private:
int tid_; int tid_;
int parent_tid_; int parent_tid_;

View File

@ -32,7 +32,7 @@ AsanThreadRegistry::AsanThreadRegistry(LinkerInitialized x)
mu_(x) { } mu_(x) { }
void AsanThreadRegistry::Init() { void AsanThreadRegistry::Init() {
AsanTSDInit(); AsanTSDInit(AsanThreadSummary::TSDDtor);
main_thread_.set_summary(&main_thread_summary_); main_thread_.set_summary(&main_thread_summary_);
main_thread_summary_.set_thread(&main_thread_); main_thread_summary_.set_thread(&main_thread_);
RegisterThread(&main_thread_); RegisterThread(&main_thread_);

View File

@ -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 #ifdef __EXCEPTIONS
__attribute__((noinline)) __attribute__((noinline))
static void StackReuseAndException() { static void StackReuseAndException() {