As was reported in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77982, there is possible deadlock in dynamic ASan runtime when we dlopen() shared lib which creates a thread at the global initialization stage. Here is the scenario:
- dlopen grabs a GI_pthread_mutex_lock in main thread.
- main thread calls pthread_create, ASan intercepts it, calls real pthread_create and waits for the second thread to be "fully initialized".
- Newly created thread tries to access a thread local disable_counter in LSan (to complete its "full initialization") and hangs in tls_get_addr_tail, because it also tries to acquire GI_pthread_mutex_lock.
The issue doesn't reproduce on older Glibc (e.g. 2.19 on my Ubuntu box) because tls_get_addr_tail doesn't try to acquire GI_pthread_mutex_lock there, but reproducible on more recent ones, e.g. Glibc 2.23.
The deadlock doesn't occur with ASan static linkage because in this case disable_counter resides in static tls, thus tls_get_addr_tail isn't called.
The simple fix would be just using attribute((tls_model("initial-exec"))) for disable_counter in LSan. This should be fine since nobody would dlopen {A, L}San runtime in any case.