Index: lib/lsan/lsan_common.cc =================================================================== --- lib/lsan/lsan_common.cc +++ lib/lsan/lsan_common.cc @@ -32,6 +32,7 @@ // also to protect the global list of root regions. BlockingMutex global_mutex(LINKER_INITIALIZED); +__attribute__((tls_model("initial-exec"))) THREADLOCAL int disable_counter; bool DisabledInThisThread() { return disable_counter > 0; } void DisableInThisThread() { disable_counter++; } Index: test/asan/TestCases/Linux/pthread_create_from_constructor.cc =================================================================== --- /dev/null +++ test/asan/TestCases/Linux/pthread_create_from_constructor.cc @@ -0,0 +1,48 @@ +// Test that ASan doesn't deadlock in __interceptor_pthread_create called +// from dlopened shared library constructor. The deadlock happens only in shared +// ASan runtime with recent Glibc (2.23 fits) when __interceptor_pthread_create +// grabs global Glibc's GL(dl_load_lock) and waits for tls_get_addr_tail that +// also tries to acquire it. +// +// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %t-so.so +// RUN: %clangxx_asan %s -o %t +// RUN: %run %t 2>&1 + +// dlopen() can not be intercepted on Android +// UNSUPPORTED: android + +#ifdef BUILD_SO + +#include +#include +#include + +void *threadFn(void *) { + fprintf(stderr, "thread started\n"); + while (true) { + usleep(100000); + } + return 0; +} + +void __attribute__((constructor)) startPolling() { + fprintf(stderr, "initializing library\n"); + pthread_t t; + pthread_create(&t, 0, &threadFn, 0); + fprintf(stderr, "done\n"); +} + +#else + +#include +#include +#include + +int main(int argc, char **argv) { + std::string path = std::string(argv[0]) + "-so.so"; + void *handle = dlopen(path.c_str(), RTLD_LAZY); + if (!handle) + abort(); + return 0; +} +#endif