Fix dlclose for libraries with thread_local dtors
Introduce new flag to mark soinfo as TLS_NODELETE when
there are thread_local dtors associated with dso_handle
belonging to it.
Test: bionic-unit-tests --gtest_filter=dl*
Test: bionic-unit-tests-glibc --gtest_filter=dl*
Bug: https://github.com/android-ndk/ndk/issues/360
Change-Id: I724ef89fc899788f95c47e6372c38b3313f18fed
diff --git a/libc/Android.bp b/libc/Android.bp
index 20648d0..a0748a9 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1706,15 +1706,18 @@
// Do not pack libc.so relocations; see http://b/20645321 for details.
pack_relocations: false,
- // WARNING: The only library libc.so should depend on is libdl.so! If you add other libraries,
- // make sure to add -Wl,--exclude-libs=libgcc.a to the LOCAL_LDFLAGS for those libraries. This
- // ensures that symbols that are pulled into those new libraries from libgcc.a are not declared
- // external; if that were the case, then libc would not pull those symbols from libgcc.a as it
- // should, instead relying on the external symbols from the dependent libraries. That would
- // create a "cloaked" dependency on libgcc.a in libc though the libraries, which is not what
- // you wanted!
+ // WARNING: The only libraries libc.so should depend on are libdl.so and ld-android.so!
+ // If you add other libraries, make sure to add -Wl,--exclude-libs=libgcc.a to the
+ // LOCAL_LDFLAGS for those libraries. This ensures that symbols that are pulled into
+ // those new libraries from libgcc.a are not declared external; if that were the case,
+ // then libc would not pull those symbols from libgcc.a as it should, instead relying
+ // on the external symbols from the dependent libraries. That would create a "cloaked"
+ // dependency on libgcc.a in libc though the libraries, which is not what you wanted!
- shared_libs: ["libdl"],
+ shared_libs: [
+ "ld-android",
+ "libdl",
+ ],
whole_static_libs: ["libc_common", "libjemalloc"],
nocrt: true,
diff --git a/libc/bionic/__cxa_thread_atexit_impl.cpp b/libc/bionic/__cxa_thread_atexit_impl.cpp
index f687fd1..99077c1 100644
--- a/libc/bionic/__cxa_thread_atexit_impl.cpp
+++ b/libc/bionic/__cxa_thread_atexit_impl.cpp
@@ -28,6 +28,8 @@
};
extern "C" int __cxa_thread_atexit_impl(void (*func) (void *), void *arg, void *dso_handle);
+extern "C" void __loader_add_thread_local_dtor(void* dso_handle) __attribute__((weak));
+extern "C" void __loader_remove_thread_local_dtor(void* dso_handle) __attribute__((weak));
__BIONIC_WEAK_FOR_NATIVE_BRIDGE
int __cxa_thread_atexit_impl(void (*func) (void *), void *arg, void *dso_handle) {
@@ -40,6 +42,9 @@
pthread_internal_t* thread = __get_thread();
dtor->next = thread->thread_local_dtors;
thread->thread_local_dtors = dtor;
+ if (__loader_add_thread_local_dtor != nullptr) {
+ __loader_add_thread_local_dtor(dso_handle);
+ }
return 0;
}
@@ -50,6 +55,9 @@
thread->thread_local_dtors = current->next;
current->func(current->arg);
+ if (__loader_remove_thread_local_dtor != nullptr) {
+ __loader_remove_thread_local_dtor(current->dso_handle);
+ }
delete current;
}
}