Wait for JIT threads to be created in ASAN builds
A race between pthread_create and dlopen could cause deadlock in ASAN
builds with older glibc versions. The pthread_create sanitizer
interceptor uses dl_iterate_phdr with a callback that uses __tls__addr.
__tls_addr could wait on dl_load_lock when there is a dlopen in progress
on other thread in older versions of glibc. dl_iterate_phdr already
holds this lock which could cause a deadlock. As a workaround for this
issue we wait for jit threads creation to finish before loading the
system library (which could dlopen) to prevent this race.
Bug: 238730394
Test: art/test.py
Change-Id: Ic7f71e4a3eaab847c878c2a08c6bcf25b6a03a3d
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 80d8a3b..f53a216 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1004,6 +1004,22 @@
}
CreateJitCodeCache(/*rwx_memory_allowed=*/true);
CreateJit();
+#ifdef ADDRESS_SANITIZER
+ // (b/238730394): In older implementations of sanitizer + glibc there is a race between
+ // pthread_create and dlopen that could cause a deadlock. pthread_create interceptor in ASAN
+ // uses dl_pthread_iterator with a callback that could request a dl_load_lock via call to
+ // __tls_get_addr [1]. dl_pthread_iterate would already hold dl_load_lock so this could cause a
+ // deadlock. __tls_get_addr needs a dl_load_lock only when there is a dlopen happening in
+ // parallel. As a workaround we wait for the pthread_create (i.e JIT thread pool creation) to
+ // finish before going to the next phase. Creating a system class loader could need a dlopen so
+ // we wait here till threads are initialized.
+ // [1] https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp#L408
+ // See this for more context: https://reviews.llvm.org/D98926
+ // TODO(b/238730394): Revisit this workaround once we migrate to musl libc.
+ if (jit_ != nullptr) {
+ jit_->GetThreadPool()->WaitForWorkersToBeCreated();
+ }
+#endif
}
// Send the start phase event. We have to wait till here as this is when the main thread peer