diff --git a/ChangeLog b/ChangeLog index 8b4d1a3bce..519478df95 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2015-07-24 Siddhesh Poyarekar + + [BZ #18457] + * nptl/Makefile (tests): New test case tst-join7. + (modules-names): New test case module tst-join7mod. + * nptl/tst-join7.c: New file. + * nptl/tst-join7mod.c: New file. + * Makeconfig (tls-model): Pass -ftls-model=initial-exec for + all translation units in libc.so, libpthread.so and rtld. + 2015-07-24 Adhemerval Zanella * sysdeps/powerpc/fpu/libm-test-ulps: Update. diff --git a/Makeconfig b/Makeconfig index 7b46323bd2..f136b88da1 100644 --- a/Makeconfig +++ b/Makeconfig @@ -858,6 +858,10 @@ in-module = $(subst -,_,$(firstword $(libof-$(basename $(@F))) \ $(libof-$(@F)) \ libc)) +# Build ld.so, libc.so and libpthread.so with -ftls-model=initial-exec +tls-model = $(if $(filter libpthread rtld \ + libc,$(in-module)),-ftls-model=initial-exec,) + module-cppflags-real = -include $(common-objpfx)libc-modules.h \ -DMODULE_NAME=$(in-module) @@ -883,7 +887,7 @@ CPPFLAGS = $(config-extra-cppflags) $(CPPUNDEFS) $(CPPFLAGS-config) \ override CFLAGS = -std=gnu99 $(gnu89-inline-CFLAGS) $(config-extra-cflags) \ $(filter-out %frame-pointer,$(+cflags)) $(+gccwarn-c) \ $(sysdep-CFLAGS) $(CFLAGS-$(suffix $@)) $(CFLAGS-$(. */ + +#include + +/* When one dynamically loads a module, which spawns a thread to perform some + activities, it could be possible that TLS storage is accessed for the first + time in that thread. This results in an allocation request within the + thread, which could result in an attempt to take the rtld load_lock. This + is a problem because it would then deadlock with the dlopen (which owns the + lock), if the main thread is waiting for the spawned thread to exit. We can + at least ensure that this problem does not occur due to accesses within + libc.so, by marking TLS variables within libc.so as IE. The problem of an + arbitrary variable being accessed and constructed within such a thread still + exists but this test case does not verify that. */ + +int +do_test (void) +{ + void *f = dlopen ("tst-join7mod.so", RTLD_NOW | RTLD_GLOBAL); + if (f) + dlclose (f); + else + return 1; + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/nptl/tst-join7mod.c b/nptl/tst-join7mod.c new file mode 100644 index 0000000000..92bb381705 --- /dev/null +++ b/nptl/tst-join7mod.c @@ -0,0 +1,61 @@ +/* Verify that TLS access in separate thread in a dlopened library does not + deadlock - the module. + Copyright (C) 2015 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 + . */ + +#include +#include +#include + +static pthread_t th; +static int running = 1; + +static void * +test_run (void *p) +{ + while (atomic_load_relaxed (&running)) + printf ("Test running\n"); + printf ("Test finished\n"); + return NULL; +} + +static void __attribute__ ((constructor)) +do_init (void) +{ + int ret = pthread_create (&th, NULL, test_run, NULL); + + if (ret != 0) + { + printf ("failed to create thread: %s (%d)\n", strerror (ret), ret); + exit (1); + } +} + +static void __attribute__ ((destructor)) +do_end (void) +{ + atomic_store_relaxed (&running, 0); + int ret = pthread_join (th, NULL); + + if (ret != 0) + { + printf ("pthread_join: %s(%d)\n", strerror (ret), ret); + exit (1); + } + + printf ("Thread joined\n"); +}