diff options
-rw-r--r-- | ChangeLog | 2 | ||||
-rw-r--r-- | elf/Makefile | 4 | ||||
-rw-r--r-- | elf/dl-close.c | 8 | ||||
-rw-r--r-- | elf/tst-thrlock.c | 55 |
4 files changed, 62 insertions, 7 deletions
@@ -5,6 +5,8 @@ (_dl_close): Call _dl_close_worker after locking and checking. * elf/dl-open.c (_dl_open): Call _dl_close_worker instead of _dl_close. + * elf/Makefile: Add rules to build and run tst-thrlock. + * elf/tst-thrlock.c: New file. [BZ #3426] * stdlib/stdlib.h: Adjust comment for canonicalize_file_name to diff --git a/elf/Makefile b/elf/Makefile index b1a9bab022..06e376d803 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -171,7 +171,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \ tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \ unload3 unload4 unload5 unload6 unload7 tst-global1 order2 \ tst-audit1 tst-audit2 \ - tst-stackguard1 tst-addr1 + tst-stackguard1 tst-addr1 tst-thrlock # reldep9 test-srcs = tst-pathopt tests-vis-yes = vismain @@ -916,3 +916,5 @@ $(objpfx)tst-leaks1-mem: $(objpfx)tst-leaks1.out tst-leaks1-ENV = MALLOC_TRACE=$(objpfx)tst-leaks1.mtrace $(objpfx)tst-addr1: $(libdl) + +$(objpfx)tst-thrlock: $(libdl) $(shared-thread-library) diff --git a/elf/dl-close.c b/elf/dl-close.c index 51f813defc..fdd9fe6719 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -110,10 +110,6 @@ void _dl_close_worker (struct link_map *map) { Lmid_t ns = map->l_ns; - unsigned int i; - - /* Acquire the lock. */ - __rtld_lock_lock_recursive (GL(dl_load_lock)); /* One less direct use. */ --map->l_direct_opencount; @@ -236,7 +232,7 @@ _dl_close_worker (struct link_map *map) #endif bool unload_any = false; unsigned int first_loaded = ~0; - for (i = 0; i < nloaded; ++i) + for (unsigned int i = 0; i < nloaded; ++i) { struct link_map *imap = maps[i]; @@ -472,7 +468,7 @@ _dl_close_worker (struct link_map *map) /* Check each element of the search list to see if all references to it are gone. */ - for (i = first_loaded; i < nloaded; ++i) + for (unsigned int i = first_loaded; i < nloaded; ++i) { struct link_map *imap = maps[i]; if (!used[i]) diff --git a/elf/tst-thrlock.c b/elf/tst-thrlock.c new file mode 100644 index 0000000000..71f1fbb35d --- /dev/null +++ b/elf/tst-thrlock.c @@ -0,0 +1,55 @@ +#include <dlfcn.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <gnu/lib-names.h> + +static void * +tf (void *arg) +{ + void *h = dlopen (LIBM_SO, RTLD_LAZY); + if (h == NULL) + { + printf ("dlopen failed: %s\n", dlerror ()); + exit (1); + } + if (dlsym (h, "sin") == NULL) + { + printf ("dlsym failed: %s\n", dlerror ()); + exit (1); + } + if (dlclose (h) != 0) + { + printf ("dlclose failed: %s\n", dlerror ()); + exit (1); + } + return NULL; +} + +int +main (void) +{ +#define N 10 + pthread_t th[N]; + for (int i = 0; i < N; ++i) + { + int e = pthread_create (&th[i], NULL, tf, NULL); + if (e != 0) + { + printf ("pthread_create failed with %d (%s)\n", e, strerror (e)); + return 1; + } + } + for (int i = 0; i < N; ++i) + { + void *res; + int e = pthread_join (th[i], &res); + if (e != 0 || res != NULL) + { + puts ("thread failed"); + return 1; + } + } + return 0; +} |