This is the mail archive of the
glibc-cvs@sourceware.org
mailing list for the glibc project.
[glibc/google/grte/v5-2.27/master] Add a case to async-signal-safe TLS to set static TLS instead of waiting for a dlopen that may not a
- From: Stan Shebs <shebs at sourceware dot org>
- To: glibc-cvs at sourceware dot org
- Date: 8 Nov 2019 21:42:52 -0000
- Subject: [glibc/google/grte/v5-2.27/master] Add a case to async-signal-safe TLS to set static TLS instead of waiting for a dlopen that may not a
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=422e4473528fa0ff036bbee4b120740958075bd9
commit 422e4473528fa0ff036bbee4b120740958075bd9
Author: Stan Shebs <stanshebs@google.com>
Date: Fri Nov 8 13:41:17 2019 -0800
Add a case to async-signal-safe TLS to set static TLS instead of waiting for a dlopen that may not actually be happening.
Diff:
---
elf/dl-tls.c | 27 +++++++++++++++++++++++++--
1 file changed, 25 insertions(+), 2 deletions(-)
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
index 592512f..0ebd1fa 100644
--- a/elf/dl-tls.c
+++ b/elf/dl-tls.c
@@ -931,8 +931,8 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
into static storage. If that happens, we have to be more careful
about initializing the area, as that dlopen() will be iterating
the threads to do so itself. */
- ptrdiff_t offset;
- if ((offset = the_map->l_tls_offset) == NO_TLS_OFFSET)
+ ptrdiff_t offset = the_map->l_tls_offset;
+ if (offset == NO_TLS_OFFSET)
{
/* l_tls_offset starts out at NO_TLS_OFFSET, and all attempts to
change it go from NO_TLS_OFFSET to some other value. We use
@@ -957,6 +957,29 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
(int) sizeof (void *) * 2,
(unsigned long int) dtv[GET_ADDR_MODULE].pointer.val);
}
+ /* It can happen that slot info updates will un-allocate a pointer (possibly
+ due to a bug elsewhere), which leaves us waiting indefinitely for the
+ dlopen that will never happen. Emulate the async-signal-unsafe case above
+ and use a static TLS address. */
+ else if (dtv[GET_ADDR_MODULE].pointer.val == TLS_DTV_UNALLOCATED)
+ {
+#if TLS_TCB_AT_TP
+ void *p = (char *) THREAD_SELF - the_map->l_tls_offset;
+#elif TLS_DTV_AT_TP
+ void *p = (char *) THREAD_SELF + the_map->l_tls_offset + TLS_PRE_TCB_SIZE;
+#else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+#endif
+ dtv[GET_ADDR_MODULE].pointer.to_free = NULL;
+ dtv[GET_ADDR_MODULE].pointer.val = p;
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_TLS))
+ _dl_debug_printf ("tls_get_addr_tail sets unallocated own dtv 0x%0*Zx module %lu pointer.val = 0x%0*Zx\n",
+ (int) sizeof (void *) * 2,
+ (unsigned long int) dtv,
+ GET_ADDR_MODULE,
+ (int) sizeof (void *) * 2,
+ (unsigned long int) dtv[GET_ADDR_MODULE].pointer.val);
+ }
else
{
void ** volatile pp = &dtv[GET_ADDR_MODULE].pointer.val;