Make dlerror(3) thread-safe.
I gave up trying to use the usual thread-local buffer idiom; calls to
calloc(3) and free(3) from any of the "dl" functions -- which live in
the dynamic linker -- end up resolving to the dynamic linker's stubs.
I tried to work around that, but was just making things more complicated.
This alternative costs us a well-known TLS slot (instead of the
dynamically-allocated TLS slot we'd have used otherwise, so no difference
there), plus an extra buffer inside every pthread_internal_t.
Bug: 5404023
Change-Id: Ie9614edd05b6d1eeaf7bf9172792d616c6361767
diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c
index da3a551..719bc83 100644
--- a/libc/bionic/pthread.c
+++ b/libc/bionic/pthread.c
@@ -163,20 +163,20 @@
}
-void __init_tls(void** tls, void* thread)
-{
- int nn;
+void __init_tls(void** tls, void* thread) {
+ ((pthread_internal_t*) thread)->tls = tls;
- ((pthread_internal_t*)thread)->tls = tls;
+ // Zero-initialize all the slots.
+ for (size_t i = 0; i < BIONIC_TLS_SLOTS; ++i) {
+ tls[i] = NULL;
+ }
- // slot 0 must point to the tls area, this is required by the implementation
- // of the x86 Linux kernel thread-local-storage
- tls[TLS_SLOT_SELF] = (void*)tls;
- tls[TLS_SLOT_THREAD_ID] = thread;
- for (nn = TLS_SLOT_ERRNO; nn < BIONIC_TLS_SLOTS; nn++)
- tls[nn] = 0;
+ // Slot 0 must point to the tls area, this is required by the implementation
+ // of the x86 Linux kernel thread-local-storage.
+ tls[TLS_SLOT_SELF] = (void*) tls;
+ tls[TLS_SLOT_THREAD_ID] = thread;
- __set_tls( (void*)tls );
+ __set_tls((void*) tls);
}