forked from OSchip/llvm-project
[asan] make sure the AsanThread object is destroyed if pthread_exit is called
llvm-svn: 149940
This commit is contained in:
parent
a2bbac3ffc
commit
b5eb5a7a05
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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_;
|
||||||
|
|
|
@ -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_);
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
Loading…
Reference in New Issue