Why do Glibc needs to hold a lock in tls_get_addr_tail?

Maxim chefmax7@gmail.com
Tue Dec 20 10:18:00 GMT 2016


I'm sorry, it seems that my mail client malformed the message .

On 20/12/16 12:55, Maxim Ostapenko wrote:
> Hi Glibc developers,
>
> I had several issues with TLS on our system (BZ #17620 and BZ #18457
> actually) and fortunately was able to fix them with corresponding
> patches.
> However, during investigation, I tried to understand details of TLS
> implementation in Glibc (I was looking to current trunk) and was
> confused by some code paths.
> In particular, I can't understand following comment in
> tls_get_addr_tail function:
>
> static void *
> __attribute_noinline__
> tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
> {
>    [...]
>    /* Make sure that, if a dlopen running in parallel forces the
>       variable into static storage, we'll wait until the address in the
>       static TLS block is set up, and use that.  If we're undecided
>       yet, make sure we make the decision holding the lock as well.  */
>    if (__glibc_unlikely (the_map->l_tls_offset
>                          != FORCED_DYNAMIC_TLS_OFFSET))
>      {
>        __rtld_lock_lock_recursive (GL(dl_load_lock));
>        if (__glibc_likely (the_map->l_tls_offset == NO_TLS_OFFSET))
>          {
>            the_map->l_tls_offset = FORCED_DYNAMIC_TLS_OFFSET;
>            __rtld_lock_unlock_recursive (GL(dl_load_lock));
>          }
>        else if (__glibc_likely (the_map->l_tls_offset
>                                 != FORCED_DYNAMIC_TLS_OFFSET))
>          {
>
>
> How could it be that dynamic linker resolves thread local symbol to a
> library that still not loaded (dlopen still running)?
> The only case I can imagine here is something like this:
>
> Thread 1
>    Thread 2
>
> while (!sym)
>   dlopen ("libfoo.so". RTLD_GLOBAL);
>    sym = dlsym (RTLD_DEFAULT, "foo");
> *sym = ...
>
> where "foo" is defined in libfoo.so library.

The testcase I was talking about looks like this:

Thread 1:

while (!sym)
    sym = dlsym (RTLD_DEFAULT, "foo");
*sym = ...

Thread 2:

dlopen ("libfoo.so". RTLD_GLOBAL);
...

where "foo" is defined in libfoo.so library.

>
> Is that the case we need to protect with lock inside
> tls_get_addr_tail? Or maybe there is another test case for this code
> path (perhaps in Glibc testsuite)?
>
> Thanks,
> -Maxim



More information about the Libc-help mailing list