mirror of
https://sourceware.org/git/glibc.git
synced 2025-01-03 08:11:08 +00:00
C++11 thread_local destructors support
This feature is specifically for the C++ compiler to offload calling thread_local object destructors on thread program exit, to glibc. This is to overcome the possible complication of destructors of thread_local objects getting called after the DSO in which they're defined is unloaded by the dynamic linker. The DSO is marked as 'unloadable' if it has a constructed thread_local object and marked as 'unloadable' again when all the constructed thread_local objects defined in it are destroyed.
This commit is contained in:
parent
ffaa74cf68
commit
ba384f6ed9
33
ChangeLog
33
ChangeLog
@ -1,5 +1,38 @@
|
||||
2013-02-18 Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
|
||||
* Versions.def: Add GLIBC_2.18.
|
||||
* include/link.h (struct link_map): New member l_tls_dtor_count.
|
||||
* include/stdlib.h (__cxa_thread_atexit_impl): Declare.
|
||||
(__call_tls_dtors): Likewise.
|
||||
* sysdeps/unix/sysv/linux/i386/nptl/libc.abilist: Add
|
||||
__cxa_thread_atexit_impl.
|
||||
* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/nptl/libc.abilist:
|
||||
Likewise.
|
||||
* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libc.abilist:
|
||||
Likewise.
|
||||
* sysdeps/unix/sysv/linux/s390/s390-32/nptl/libc.abilist:
|
||||
Likewise.
|
||||
* sysdeps/unix/sysv/linux/s390/s390-64/nptl/libc.abilist:
|
||||
Likewise.
|
||||
* sysdeps/unix/sysv/linux/sh/nptl/libc.abilist: Likewise.
|
||||
* sysdeps/unix/sysv/linux/sparc/sparc32/nptl/libc.abilist:
|
||||
Likewise.
|
||||
* sysdeps/unix/sysv/linux/sparc/sparc64/nptl/libc.abilist:
|
||||
Likewise.
|
||||
* sysdeps/unix/sysv/linux/x86_64/64/nptl/libc.abilist: Likewise.
|
||||
* sysdeps/unix/sysv/linux/x86_64/x32/nptl/libc.abilist:
|
||||
Likewise.
|
||||
* stdlib/Makefile (routines): Add __cxa_thread_atexit_impl.
|
||||
(tests): Add test case tst-tls-atexit.
|
||||
(modules-names): Add shared library for tst-tls-atexit.
|
||||
* stdlib/Versions (GLIBC_2.17): Add __cxa_thread_atexit_impl.
|
||||
(GLIBC_PRIVATE): Add __call_tls_dtors.
|
||||
* stdlib/cxa_thread_atexit_impl.c: New file with helper function
|
||||
for libstdc++.
|
||||
* stdlib/exit.c (__run_exit_handlers): Call __call_tls_dtors.
|
||||
* stdlib/tst-tls-atexit.c: New test case.
|
||||
* stdlib/tst-tls-atexit-lib.c: New test case.
|
||||
|
||||
* misc/tst-pselect.c: Include stdlib.h for declaration of exit.
|
||||
* nptl/sysdeps/pthread/tst-timer.c: Likewise.
|
||||
* nptl/tst-barrier4.c: Likewise.
|
||||
|
@ -34,6 +34,7 @@ libc {
|
||||
GLIBC_2.15
|
||||
GLIBC_2.16
|
||||
GLIBC_2.17
|
||||
GLIBC_2.18
|
||||
HURD_CTHREADS_0.3
|
||||
%ifdef EXPORT_UNWIND_FIND_FDE
|
||||
GCC_3.0
|
||||
|
@ -302,6 +302,9 @@ struct link_map
|
||||
/* Index of the module in the dtv array. */
|
||||
size_t l_tls_modid;
|
||||
|
||||
/* Number of thread_local objects constructed by this DSO. */
|
||||
size_t l_tls_dtor_count;
|
||||
|
||||
/* Information used to change permission after the relocations are
|
||||
done. */
|
||||
ElfW(Addr) l_relro_addr;
|
||||
|
@ -100,6 +100,11 @@ extern int __cxa_atexit (void (*func) (void *), void *arg, void *d);
|
||||
extern int __cxa_atexit_internal (void (*func) (void *), void *arg, void *d)
|
||||
attribute_hidden;
|
||||
|
||||
extern int __cxa_thread_atexit_impl (void (*func) (void *), void *arg,
|
||||
void *d);
|
||||
extern void __call_tls_dtors (void);
|
||||
libc_hidden_proto (__call_tls_dtors);
|
||||
|
||||
extern void __cxa_finalize (void *d);
|
||||
|
||||
extern int __posix_memalign (void **memptr, size_t alignment, size_t size);
|
||||
|
@ -311,6 +311,9 @@ start_thread (void *arg)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Call destructors for the thread_local TLS variables. */
|
||||
__call_tls_dtors ();
|
||||
|
||||
/* Run the destructor for the thread-local data. */
|
||||
__nptl_deallocate_tsd ();
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
2013-02-18 Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
|
||||
* sysdeps/unix/sysv/linux/alpha/nptl/libc.abilist: Add
|
||||
__cxa_thread_atexit_impl.
|
||||
|
||||
2013-02-14 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
[BZ #13550]
|
||||
|
@ -1,3 +1,8 @@
|
||||
2013-02-18 Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
|
||||
* sysdeps/unix/sysv/linux/arm/nptl/libc.abilist: Add
|
||||
__cxa_thread_atexit_impl.
|
||||
|
||||
2013-02-13 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
[BZ #13550]
|
||||
|
@ -1,3 +1,8 @@
|
||||
2013-02-18 Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
|
||||
* sysdeps/unix/sysv/linux/ia64/nptl/libc.abilist: Add
|
||||
__cxa_thread_atexit_impl.
|
||||
|
||||
2013-02-08 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
[BZ #13550]
|
||||
|
@ -1,3 +1,10 @@
|
||||
2013-02-18 Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
|
||||
* sysdeps/unix/sysv/linux/m68k/coldfire/nptl/libc.abilist: Add
|
||||
__cxa_thread_atexit_impl.
|
||||
* sysdeps/unix/sysv/linux/m68k/m680x0/nptl/libc.abilist:
|
||||
Likewise.
|
||||
|
||||
2013-02-08 Andreas Schwab <schwab@linux-m68k.org>
|
||||
|
||||
* sysdeps/unix/sysv/linux/m68k/kernel-features.h
|
||||
|
@ -1,3 +1,12 @@
|
||||
2013-02-18 Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
|
||||
* sysdeps/unix/sysv/linux/mips/mips32/nptl/libc.abilist: Add
|
||||
__cxa_thread_atexit_impl.
|
||||
* sysdeps/unix/sysv/linux/mips/mips64/n32/nptl/libc.abilist:
|
||||
Likewise.
|
||||
* sysdeps/unix/sysv/linux/mips/mips64/n64/nptl/libc.abilist:
|
||||
Likewise.
|
||||
|
||||
2013-02-13 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
[BZ #13550]
|
||||
|
@ -1,3 +1,10 @@
|
||||
2013-02-18 Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
|
||||
* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/nptl/libc.abilist:
|
||||
Add __cxa_thread_atexit_impl.
|
||||
* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/nptl/libc.abilist:
|
||||
Likewise.
|
||||
|
||||
2013-02-14 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
[BZ #13550]
|
||||
|
@ -1,3 +1,10 @@
|
||||
2013-02-18 Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
|
||||
* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/nptl/libc.abilist:
|
||||
Add __cxa_thread_atexit_impl.
|
||||
* sysdeps/unix/sysv/linux/tile/tilepro/nptl/libc.abilist:
|
||||
Likewise.
|
||||
|
||||
2013-01-10 Chris Metcalf <cmetcalf@tilera.com>
|
||||
|
||||
* sysdeps/unix/sysv/linux/tile/tilegx/ldd-rewrite.sed: New file.
|
||||
|
@ -1819,6 +1819,9 @@ GLIBC_2.17
|
||||
clock_nanosleep F
|
||||
clock_settime F
|
||||
secure_getenv F
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
GLIBC_2.2
|
||||
GLIBC_2.2 A
|
||||
_IO_adjust_wcolumn F
|
||||
|
@ -86,6 +86,9 @@ GLIBC_2.17
|
||||
clock_nanosleep F
|
||||
clock_settime F
|
||||
secure_getenv F
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
GLIBC_2.4
|
||||
GLIBC_2.4 A
|
||||
_Exit F
|
||||
|
@ -86,6 +86,9 @@ GLIBC_2.17
|
||||
clock_nanosleep F
|
||||
clock_settime F
|
||||
secure_getenv F
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
GLIBC_2.2
|
||||
GLIBC_2.2 A
|
||||
_Exit F
|
||||
|
@ -87,6 +87,9 @@ GLIBC_2.17
|
||||
clock_nanosleep F
|
||||
clock_settime F
|
||||
secure_getenv F
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
GLIBC_2.4
|
||||
GLIBC_2.4 A
|
||||
_Exit F
|
||||
|
@ -1775,6 +1775,9 @@ GLIBC_2.17
|
||||
clock_nanosleep F
|
||||
clock_settime F
|
||||
secure_getenv F
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
GLIBC_2.2
|
||||
GLIBC_2.2 A
|
||||
_IO_adjust_wcolumn F
|
||||
|
@ -2250,3 +2250,6 @@ GLIBC_2.17
|
||||
clock_nanosleep F
|
||||
clock_settime F
|
||||
secure_getenv F
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
|
@ -1398,6 +1398,9 @@ GLIBC_2.17
|
||||
clock_nanosleep F
|
||||
clock_settime F
|
||||
secure_getenv F
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
GLIBC_2.2
|
||||
GLIBC_2.2 A
|
||||
_Exit F
|
||||
|
@ -1396,6 +1396,9 @@ GLIBC_2.17
|
||||
clock_nanosleep F
|
||||
clock_settime F
|
||||
secure_getenv F
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
GLIBC_2.2
|
||||
GLIBC_2.2 A
|
||||
_Exit F
|
||||
|
@ -1781,6 +1781,9 @@ GLIBC_2.17
|
||||
clock_nanosleep F
|
||||
clock_settime F
|
||||
secure_getenv F
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
GLIBC_2.2
|
||||
GLIBC_2.2 A
|
||||
_IO_adjust_wcolumn F
|
||||
|
@ -2088,3 +2088,6 @@ GLIBC_2.17
|
||||
clock_nanosleep F
|
||||
clock_settime F
|
||||
secure_getenv F
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
|
@ -2088,3 +2088,6 @@ GLIBC_2.17
|
||||
clock_nanosleep F
|
||||
clock_settime F
|
||||
secure_getenv F
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
|
@ -2088,3 +2088,6 @@ GLIBC_2.17
|
||||
clock_nanosleep F
|
||||
clock_settime F
|
||||
secure_getenv F
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
|
@ -34,7 +34,7 @@ routines := \
|
||||
bsearch qsort msort \
|
||||
getenv putenv setenv secure-getenv \
|
||||
exit on_exit atexit cxa_atexit cxa_finalize old_atexit \
|
||||
quick_exit at_quick_exit cxa_at_quick_exit \
|
||||
quick_exit at_quick_exit cxa_at_quick_exit cxa_thread_atexit_impl \
|
||||
abs labs llabs \
|
||||
div ldiv lldiv \
|
||||
mblen mbstowcs mbtowc wcstombs wctomb \
|
||||
@ -71,9 +71,11 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
|
||||
tst-makecontext2 tst-strtod6 tst-unsetenv1 \
|
||||
tst-makecontext3 bug-getcontext bug-fmtmsg1 \
|
||||
tst-secure-getenv tst-strtod-overflow tst-strtod-round \
|
||||
tst-tininess tst-strtod-underflow
|
||||
tst-tininess tst-strtod-underflow tst-tls-atexit
|
||||
tests-static := tst-secure-getenv
|
||||
|
||||
modules-names = tst-tls-atexit-lib
|
||||
|
||||
include ../Makeconfig
|
||||
|
||||
ifeq ($(build-shared),yes)
|
||||
@ -155,3 +157,9 @@ $(objpfx)bug-getcontext: $(link-libm)
|
||||
$(objpfx)tst-strtod-round: $(link-libm)
|
||||
$(objpfx)tst-tininess: $(link-libm)
|
||||
$(objpfx)tst-strtod-underflow: $(link-libm)
|
||||
|
||||
tst-tls-atexit-lib.so-no-z-defs = yes
|
||||
|
||||
LDFLAGS-tst-tls-atexit = $(common-objpfx)nptl/libpthread.so \
|
||||
$(common-objpfx)dlfcn/libdl.so
|
||||
$(objpfx)tst-tls-atexit.out: $(objpfx)tst-tls-atexit-lib.so
|
||||
|
@ -106,6 +106,9 @@ libc {
|
||||
GLIBC_2.17 {
|
||||
secure_getenv;
|
||||
}
|
||||
GLIBC_2.18 {
|
||||
__cxa_thread_atexit_impl;
|
||||
}
|
||||
GLIBC_PRIVATE {
|
||||
# functions which have an additional interface since they are
|
||||
# are cancelable.
|
||||
@ -114,5 +117,6 @@ libc {
|
||||
__abort_msg;
|
||||
# Used from other libraries
|
||||
__libc_secure_getenv;
|
||||
__call_tls_dtors;
|
||||
}
|
||||
}
|
||||
|
102
stdlib/cxa_thread_atexit_impl.c
Normal file
102
stdlib/cxa_thread_atexit_impl.c
Normal file
@ -0,0 +1,102 @@
|
||||
/* Register destructors for C++ TLS variables declared with thread_local.
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ldsodefs.h>
|
||||
|
||||
typedef void (*dtor_func) (void *);
|
||||
|
||||
struct dtor_list
|
||||
{
|
||||
dtor_func func;
|
||||
void *obj;
|
||||
struct link_map *map;
|
||||
struct dtor_list *next;
|
||||
};
|
||||
|
||||
static __thread struct dtor_list *tls_dtor_list;
|
||||
static __thread void *dso_symbol_cache;
|
||||
static __thread struct link_map *lm_cache;
|
||||
|
||||
/* Register a destructor for TLS variables declared with the 'thread_local'
|
||||
keyword. This function is only called from code generated by the C++
|
||||
compiler. FUNC is the destructor function and OBJ is the object to be
|
||||
passed to the destructor. DSO_SYMBOL is the __dso_handle symbol that each
|
||||
DSO has at a unique address in its map, added from crtbegin.o during the
|
||||
linking phase. */
|
||||
int
|
||||
__cxa_thread_atexit_impl (dtor_func func, void *obj, void *dso_symbol)
|
||||
{
|
||||
/* Prepend. */
|
||||
struct dtor_list *new = calloc (1, sizeof (struct dtor_list));
|
||||
new->func = func;
|
||||
new->obj = obj;
|
||||
new->next = tls_dtor_list;
|
||||
tls_dtor_list = new;
|
||||
|
||||
/* See if we already encountered the DSO. */
|
||||
__rtld_lock_lock_recursive (GL(dl_load_lock));
|
||||
|
||||
if (__builtin_expect (dso_symbol_cache != dso_symbol, 0))
|
||||
{
|
||||
ElfW(Addr) caller = (ElfW(Addr)) dso_symbol;
|
||||
|
||||
struct link_map *l = _dl_find_dso_for_object (caller);
|
||||
|
||||
/* If the address is not recognized the call comes from the main
|
||||
program (we hope). */
|
||||
lm_cache = l ? l : GL(dl_ns)[LM_ID_BASE]._ns_loaded;
|
||||
}
|
||||
/* A destructor could result in a thread_local construction and the former
|
||||
could have cleared the flag. */
|
||||
if (lm_cache->l_type == lt_loaded && lm_cache->l_tls_dtor_count == 0)
|
||||
lm_cache->l_flags_1 |= DF_1_NODELETE;
|
||||
|
||||
new->map = lm_cache;
|
||||
new->map->l_tls_dtor_count++;
|
||||
|
||||
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Call the destructors. This is called either when a thread returns from the
|
||||
initial function or when the process exits via the exit(3) function. */
|
||||
void
|
||||
__call_tls_dtors (void)
|
||||
{
|
||||
while (tls_dtor_list)
|
||||
{
|
||||
struct dtor_list *cur = tls_dtor_list;
|
||||
tls_dtor_list = tls_dtor_list->next;
|
||||
|
||||
cur->func (cur->obj);
|
||||
|
||||
__rtld_lock_lock_recursive (GL(dl_load_lock));
|
||||
|
||||
/* Allow DSO unload if count drops to zero. */
|
||||
cur->map->l_tls_dtor_count--;
|
||||
if (cur->map->l_tls_dtor_count == 0 && cur->map->l_type == lt_loaded)
|
||||
cur->map->l_flags_1 &= ~DF_1_NODELETE;
|
||||
|
||||
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
|
||||
free (cur);
|
||||
}
|
||||
}
|
||||
libc_hidden_def (__call_tls_dtors)
|
@ -33,6 +33,9 @@ attribute_hidden
|
||||
__run_exit_handlers (int status, struct exit_function_list **listp,
|
||||
bool run_list_atexit)
|
||||
{
|
||||
/* First, call the TLS destructors. */
|
||||
__call_tls_dtors ();
|
||||
|
||||
/* We do it this way to handle recursive calls to exit () made by
|
||||
the functions registered with `atexit' and `on_exit'. We call
|
||||
everyone on the list and use the status value in the last
|
||||
|
36
stdlib/tst-tls-atexit-lib.c
Normal file
36
stdlib/tst-tls-atexit-lib.c
Normal file
@ -0,0 +1,36 @@
|
||||
/* Verify that DSO is unloaded only if its TLS objects are destroyed - the DSO.
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
extern void *__dso_handle;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *val;
|
||||
} A;
|
||||
|
||||
/* We only care about the destructor. */
|
||||
void A_dtor (void *obj)
|
||||
{
|
||||
((A *)obj)->val = obj;
|
||||
}
|
||||
|
||||
void do_foo (void)
|
||||
{
|
||||
static __thread A b;
|
||||
__cxa_thread_atexit_impl (A_dtor, &b, __dso_handle);
|
||||
}
|
111
stdlib/tst-tls-atexit.c
Normal file
111
stdlib/tst-tls-atexit.c
Normal file
@ -0,0 +1,111 @@
|
||||
/* Verify that DSO is unloaded only if its TLS objects are destroyed.
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* There are two tests in this test case. The first is implicit where it is
|
||||
assumed that the destructor call on exit of the LOAD function does not
|
||||
segfault. The other is a verification that after the thread has exited, a
|
||||
dlclose will unload the DSO. */
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
void *handle;
|
||||
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
void *
|
||||
load (void *u)
|
||||
{
|
||||
pthread_mutex_lock (&m);
|
||||
handle = dlopen ("$ORIGIN/tst-tls-atexit-lib.so", RTLD_LAZY);
|
||||
if (!handle)
|
||||
{
|
||||
printf ("Unable to load DSO: %s\n", dlerror ());
|
||||
return (void *) (uintptr_t) 1;
|
||||
}
|
||||
|
||||
void (*foo) (void) = (void (*) (void)) dlsym(handle, "do_foo");
|
||||
|
||||
if (!foo)
|
||||
{
|
||||
printf ("Unable to find symbol: %s\n", dlerror ());
|
||||
exit (1);
|
||||
}
|
||||
|
||||
foo ();
|
||||
|
||||
/* This should not unload the DSO. If it does, then the thread exit will
|
||||
result in a segfault. */
|
||||
dlclose (handle);
|
||||
pthread_mutex_unlock (&m);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
pthread_t t;
|
||||
int ret;
|
||||
void *thr_ret;
|
||||
|
||||
if ((ret = pthread_create (&t, NULL, load, NULL)) != 0)
|
||||
{
|
||||
printf ("pthread_create failed: %s\n", strerror (ret));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((ret = pthread_join (t, &thr_ret)) != 0)
|
||||
{
|
||||
printf ("pthread_create failed: %s\n", strerror (ret));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (thr_ret != NULL)
|
||||
return 1;
|
||||
|
||||
/* Now this should unload the DSO. */
|
||||
dlclose (handle);
|
||||
|
||||
/* Run through our maps and ensure that the DSO is unloaded. */
|
||||
FILE *f = fopen ("/proc/self/maps", "r");
|
||||
|
||||
if (f == NULL)
|
||||
{
|
||||
perror ("Failed to open /proc/self/maps");
|
||||
fprintf (stderr, "Skipping verification of DSO unload\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *line = NULL;
|
||||
size_t s = 0;
|
||||
while (getline (&line, &s, f) > 0)
|
||||
{
|
||||
if (strstr (line, "tst-tls-atexit-lib.so"))
|
||||
{
|
||||
printf ("DSO not unloaded yet:\n%s", line);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
free (line);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1819,6 +1819,9 @@ GLIBC_2.17
|
||||
clock_nanosleep F
|
||||
clock_settime F
|
||||
secure_getenv F
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
GLIBC_2.2
|
||||
GLIBC_2.2 A
|
||||
_IO_adjust_wcolumn F
|
||||
|
@ -1781,6 +1781,9 @@ GLIBC_2.17
|
||||
clock_nanosleep F
|
||||
clock_settime F
|
||||
secure_getenv F
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
GLIBC_2.2
|
||||
GLIBC_2.2 A
|
||||
_IO_adjust_wcolumn F
|
||||
|
@ -87,6 +87,9 @@ GLIBC_2.17
|
||||
clock_nanosleep F
|
||||
clock_settime F
|
||||
secure_getenv F
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
GLIBC_2.3
|
||||
GLIBC_2.3 A
|
||||
_Exit F
|
||||
|
@ -1771,6 +1771,9 @@ GLIBC_2.17
|
||||
clock_nanosleep F
|
||||
clock_settime F
|
||||
secure_getenv F
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
GLIBC_2.2
|
||||
GLIBC_2.2 A
|
||||
_IO_adjust_wcolumn F
|
||||
|
@ -92,6 +92,9 @@ GLIBC_2.17
|
||||
clock_nanosleep F
|
||||
clock_settime F
|
||||
secure_getenv F
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
GLIBC_2.2
|
||||
GLIBC_2.2 A
|
||||
_Exit F
|
||||
|
@ -92,6 +92,9 @@ GLIBC_2.17
|
||||
clock_nanosleep F
|
||||
clock_settime F
|
||||
secure_getenv F
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
GLIBC_2.2
|
||||
GLIBC_2.2 A
|
||||
_Exit F
|
||||
|
@ -1776,6 +1776,9 @@ GLIBC_2.17
|
||||
clock_nanosleep F
|
||||
clock_settime F
|
||||
secure_getenv F
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
GLIBC_2.2
|
||||
GLIBC_2.2 A
|
||||
_IO_adjust_wcolumn F
|
||||
|
@ -97,6 +97,9 @@ GLIBC_2.17
|
||||
clock_nanosleep F
|
||||
clock_settime F
|
||||
secure_getenv F
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
GLIBC_2.2
|
||||
GLIBC_2.2 A
|
||||
_Exit F
|
||||
|
@ -88,6 +88,9 @@ GLIBC_2.17
|
||||
clock_nanosleep F
|
||||
clock_settime F
|
||||
secure_getenv F
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
GLIBC_2.2.5
|
||||
GLIBC_2.2.5 A
|
||||
_Exit F
|
||||
|
@ -2086,3 +2086,6 @@ GLIBC_2.17
|
||||
clock_nanosleep F
|
||||
clock_settime F
|
||||
secure_getenv F
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
|
Loading…
Reference in New Issue
Block a user