Fix a bug in tls initialization which caused __tls_get_addr to return NULL. We need to postpone all calls to _dl_update_slotinfo until after _dl_add_to_slotinfo is complete. This is because _dl_update_slotinfo will modify the generation of the DTV to match that of the new slot. We cannot allow this to happen until all slots of the generation have been added. 2010-01-30 Martin von Gagern References: https://github.com/cschwan/sage-on-gentoo/issues/#issue/40 https://bugs.gentoo.org/353224 Index: glibc-2.12.2/elf/dl-open.c =================================================================== --- glibc-2.12.2.orig/elf/dl-open.c +++ glibc-2.12.2/elf/dl-open.c @@ -346,7 +346,7 @@ dl_open_worker (void *a) /* If the file is not loaded now as a dependency, add the search list of the newly loaded object to the scope. */ - bool any_tls = false; + bool any_tls = false, any_static_tls = false; for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i) { struct link_map *imap = new->l_searchlist.r_list[i]; @@ -426,6 +426,25 @@ dl_open_worker (void *a) _dl_add_to_slotinfo (imap); if (imap->l_need_tls_init) + any_static_tls = true; + + /* We have to bump the generation counter. */ + any_tls = true; + } + } + + /* We need a second pass for static tls data, because _dl_update_slotinfo + must not be run while calls to _dl_add_to_slotinfo are still pending. */ + if (__builtin_expect (any_static_tls, 0)) + { + for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i) + { + struct link_map *imap = new->l_searchlist.r_list[i]; + if (__builtin_expect (imap->l_need_tls_init, 0) + /* The following two can likely be dropped, but let's be extra + safe and copy all the conditions for now. */ + && ! imap->l_init_called + && __builtin_expect (imap->l_tls_blocksize > 0, 0)) { /* For static TLS we have to allocate the memory here and now. This includes allocating memory in the DTV. @@ -449,9 +468,6 @@ cannot load any more object with static GL(dl_init_static_tls) (imap); assert (imap->l_need_tls_init == 0); } - - /* We have to bump the generation counter. */ - any_tls = true; } }