forked from OSchip/llvm-project
[tsan] For OS X thread finalization, remove g_thread_finalize_key in favor of libpthread hooks
On OS X, the thread finalization is fragile due to thread-local variables destruction order. I've seen cases where the we destroy the ThreadState too early and subsequent thread-local values' destructors call interceptors again. Let's replace the TLV-based thread finalization method with libpthread hooks. The notification PTHREAD_INTROSPECTION_THREAD_TERMINATE is called *after* all TLVs have been destroyed. Differential Revision: http://reviews.llvm.org/D14777 llvm-svn: 253560
This commit is contained in:
parent
9eb6df9f1e
commit
f503d51e5b
|
@ -233,7 +233,9 @@ static ThreadSignalContext *SigCtx(ThreadState *thr) {
|
|||
return ctx;
|
||||
}
|
||||
|
||||
#if !SANITIZER_MAC
|
||||
static unsigned g_thread_finalize_key;
|
||||
#endif
|
||||
|
||||
ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname,
|
||||
uptr pc)
|
||||
|
@ -825,6 +827,7 @@ void DestroyThreadState() {
|
|||
}
|
||||
} // namespace __tsan
|
||||
|
||||
#if !SANITIZER_MAC
|
||||
static void thread_finalize(void *v) {
|
||||
uptr iter = (uptr)v;
|
||||
if (iter > 1) {
|
||||
|
@ -836,6 +839,7 @@ static void thread_finalize(void *v) {
|
|||
}
|
||||
DestroyThreadState();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
struct ThreadParam {
|
||||
|
@ -853,6 +857,7 @@ extern "C" void *__tsan_thread_start_func(void *arg) {
|
|||
ThreadState *thr = cur_thread();
|
||||
// Thread-local state is not initialized yet.
|
||||
ScopedIgnoreInterceptors ignore;
|
||||
#if !SANITIZER_MAC
|
||||
ThreadIgnoreBegin(thr, 0);
|
||||
if (pthread_setspecific(g_thread_finalize_key,
|
||||
(void *)GetPthreadDestructorIterations())) {
|
||||
|
@ -860,6 +865,7 @@ extern "C" void *__tsan_thread_start_func(void *arg) {
|
|||
Die();
|
||||
}
|
||||
ThreadIgnoreEnd(thr, 0);
|
||||
#endif
|
||||
while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0)
|
||||
internal_sched_yield();
|
||||
ThreadStart(thr, tid, GetTid());
|
||||
|
@ -2640,10 +2646,12 @@ void InitializeInterceptors() {
|
|||
Die();
|
||||
}
|
||||
|
||||
#if !SANITIZER_MAC
|
||||
if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
|
||||
Printf("ThreadSanitizer: failed to create thread key\n");
|
||||
Die();
|
||||
}
|
||||
#endif
|
||||
|
||||
FdInit();
|
||||
}
|
||||
|
|
|
@ -124,7 +124,7 @@ typedef void (*pthread_introspection_hook_t)(unsigned int event,
|
|||
extern "C" pthread_introspection_hook_t pthread_introspection_hook_install(
|
||||
pthread_introspection_hook_t hook);
|
||||
static const uptr PTHREAD_INTROSPECTION_THREAD_CREATE = 1;
|
||||
static const uptr PTHREAD_INTROSPECTION_THREAD_DESTROY = 4;
|
||||
static const uptr PTHREAD_INTROSPECTION_THREAD_TERMINATE = 3;
|
||||
static pthread_introspection_hook_t prev_pthread_introspection_hook;
|
||||
static void my_pthread_introspection_hook(unsigned int event, pthread_t thread,
|
||||
void *addr, size_t size) {
|
||||
|
@ -137,10 +137,12 @@ static void my_pthread_introspection_hook(unsigned int event, pthread_t thread,
|
|||
ThreadState *thr = cur_thread();
|
||||
ThreadStart(thr, tid, GetTid());
|
||||
}
|
||||
} else if (event == PTHREAD_INTROSPECTION_THREAD_DESTROY) {
|
||||
ThreadState *thr = cur_thread();
|
||||
if (thr->tctx && thr->tctx->parent_tid == kInvalidTid) {
|
||||
DestroyThreadState();
|
||||
} else if (event == PTHREAD_INTROSPECTION_THREAD_TERMINATE) {
|
||||
if (thread == pthread_self()) {
|
||||
ThreadState *thr = cur_thread();
|
||||
if (thr->tctx) {
|
||||
DestroyThreadState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue