From 7880b25a1d0531e386729051f432571455180088 Mon Sep 17 00:00:00 2001 From: Kamil Rytarowski Date: Sun, 26 Nov 2017 09:42:01 +0000 Subject: Detect thread termination in LSan/NetBSD Summary: Stop using the Linux solution with pthread_key_create(3). This approach does not work on NetBSD, because calling the thread destructor is not the latest operation on a POSIX thread entity. Detect _lwp_exit(2) call as it is really the latest operation called from a detaching POSIX thread. The pthread_key_create(3) solution also cannot be used in early libc/libpthread initialization on NetBSD as the system libraries are not bootstrapped enough. Sponsored by Reviewers: joerg, vitalybuka, kcc, dvyukov Reviewed By: dvyukov Subscribers: llvm-commits, #sanitizers Tags: #sanitizers Differential Revision: https://reviews.llvm.org/D40457 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@318994 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/lsan/lsan_interceptors.cc | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'lib') diff --git a/lib/lsan/lsan_interceptors.cc b/lib/lsan/lsan_interceptors.cc index a7c0f72f6..b3e73e389 100644 --- a/lib/lsan/lsan_interceptors.cc +++ b/lib/lsan/lsan_interceptors.cc @@ -309,6 +309,7 @@ INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) ///// Thread initialization and finalization. ///// +#if !SANITIZER_NETBSD static unsigned g_thread_finalize_key; static void thread_finalize(void *v) { @@ -322,6 +323,18 @@ static void thread_finalize(void *v) { } ThreadFinish(); } +#endif + +#if SANITIZER_NETBSD +INTERCEPTOR(void, _lwp_exit) { + ENSURE_LSAN_INITED; + ThreadFinish(); + REAL(_lwp_exit)(); +} +#define LSAN_MAYBE_INTERCEPT__LWP_EXIT INTERCEPT_FUNCTION(_lwp_exit) +#else +#define LSAN_MAYBE_INTERCEPT__LWP_EXIT +#endif struct ThreadParam { void *(*callback)(void *arg); @@ -335,11 +348,13 @@ extern "C" void *__lsan_thread_start_func(void *arg) { void *param = p->param; // Wait until the last iteration to maximize the chance that we are the last // destructor to run. +#if !SANITIZER_NETBSD if (pthread_setspecific(g_thread_finalize_key, (void*)GetPthreadDestructorIterations())) { Report("LeakSanitizer: failed to set thread key.\n"); Die(); } +#endif int tid = 0; while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0) internal_sched_yield(); @@ -427,10 +442,14 @@ void InitializeInterceptors() { INTERCEPT_FUNCTION(pthread_join); INTERCEPT_FUNCTION(_exit); + LSAN_MAYBE_INTERCEPT__LWP_EXIT; + +#if !SANITIZER_NETBSD if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) { Report("LeakSanitizer: failed to create thread key.\n"); Die(); } +#endif } } // namespace __lsan -- cgit v1.2.3