Call __emutls_unregister_key on dlclose

We want to delay the emutls pthread key deletion to keep
__thread/thread_local variables working as long as possible.

Currently, emutls has its own __attribute__((destructor)) function that
deletes its pthread key. That function runs even on process exit, and it
can run before other destructor functions and before C++ static object
destructors.

Move the destructor function to crtbegin_so.c, where an
__attribute__((destructor)) function is only called on dlclose. Use a
priority 0 destructor, which runs after every destructor with a default or
greater priority value.

__emutls_unregister_key will still run before destructor functions of
DT_NEEDED solibs. It also still leaks memory (both the emutls arrays and
each emutls object).

Bug: b/80453944
Test: manual
Change-Id: I6789bcf168415ab8badf2f64687c6a0136c5c917
diff --git a/libc/arch-common/bionic/crtbegin_so.c b/libc/arch-common/bionic/crtbegin_so.c
index 3754363..cf369cc 100644
--- a/libc/arch-common/bionic/crtbegin_so.c
+++ b/libc/arch-common/bionic/crtbegin_so.c
@@ -29,11 +29,27 @@
 extern void __cxa_finalize(void *);
 extern void *__dso_handle;
 
-__attribute__((visibility("hidden"),destructor))
-void __on_dlclose() {
+__attribute__((destructor))
+static void __on_dlclose(void) {
   __cxa_finalize(&__dso_handle);
 }
 
+/* Define a weak stub function here that will be overridden if the solib uses
+ * emutls. The function needs to be a definition, not just a declaration,
+ * because gold has a bug where it outputs weak+hidden symbols into the .dynsym
+ * table. */
+__attribute__((weak,visibility("hidden")))
+void __emutls_unregister_key(void) {
+}
+
+/* Use a priority of 0 to run after any ordinary destructor function. The
+ * priority setting moves the function towards the front of the .fini_array
+ * section. */
+__attribute__((destructor(0)))
+static void __on_dlclose_late(void) {
+  __emutls_unregister_key();
+}
+
 /* CRT_LEGACY_WORKAROUND should only be defined when building
  * this file as part of the platform's C library.
  *