summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorKamil Rytarowski <n54@gmx.com>2017-11-26 09:42:01 +0000
committerKamil Rytarowski <n54@gmx.com>2017-11-26 09:42:01 +0000
commit7880b25a1d0531e386729051f432571455180088 (patch)
tree8df59de8b5e569d397e2e3f281cc92341c6ea91e /lib
parentc4f374ed3ab953d558b86ff0632ddf4b757f467b (diff)
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 <The NetBSD Foundation> 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
Diffstat (limited to 'lib')
-rw-r--r--lib/lsan/lsan_interceptors.cc19
1 files changed, 19 insertions, 0 deletions
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