about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--Makeconfig6
-rw-r--r--NEWS12
-rw-r--r--nptl/Makefile10
-rw-r--r--nptl/tst-join7.c46
-rw-r--r--nptl/tst-join7mod.c61
6 files changed, 136 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index 8b4d1a3bce..519478df95 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2015-07-24  Siddhesh Poyarekar  <siddhesh@redhat.com>
+
+	[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  <adhemerval.zanella@linaro.org>
 
 	* 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-$(<F)) \
-		  $(CFLAGS-$(@F)) \
+		  $(CFLAGS-$(@F)) $(tls-model) \
 		  $(foreach lib,$(libof-$(basename $(@F))) \
 				$(libof-$(<F)) $(libof-$(@F)),$(CFLAGS-$(lib)))
 override CXXFLAGS = $(c++-sysincludes) \
diff --git a/NEWS b/NEWS
index fbe8484656..65b2172701 100644
--- a/NEWS
+++ b/NEWS
@@ -22,12 +22,12 @@ Version 2.22
   18125, 18128, 18134, 18138, 18185, 18196, 18197, 18206, 18210, 18211,
   18217, 18219, 18220, 18221, 18234, 18244, 18245, 18247, 18287, 18319,
   18324, 18333, 18346, 18371, 18383, 18397, 18400, 18409, 18410, 18412,
-  18418, 18422, 18434, 18444, 18468, 18469, 18470, 18479, 18483, 18495,
-  18496, 18497, 18498, 18502, 18507, 18508, 18512, 18513, 18519, 18520,
-  18522, 18527, 18528, 18529, 18530, 18532, 18533, 18534, 18536, 18539,
-  18540, 18542, 18544, 18545, 18546, 18547, 18549, 18553, 18557, 18558,
-  18569, 18583, 18585, 18586, 18592, 18593, 18594, 18602, 18612, 18613,
-  18619, 18633, 18641, 18643, 18648, 18657, 18676, 18694, 18696.
+  18418, 18422, 18434, 18444, 18457, 18468, 18469, 18470, 18479, 18483,
+  18495, 18496, 18497, 18498, 18502, 18507, 18508, 18512, 18513, 18519,
+  18520, 18522, 18527, 18528, 18529, 18530, 18532, 18533, 18534, 18536,
+  18539, 18540, 18542, 18544, 18545, 18546, 18547, 18549, 18553, 18557,
+  18558, 18569, 18583, 18585, 18586, 18592, 18593, 18594, 18602, 18612,
+  18613, 18619, 18633, 18641, 18643, 18648, 18657, 18676, 18694, 18696.
 
 * Cache information can be queried via sysconf() function on s390 e.g. with
   _SC_LEVEL1_ICACHE_SIZE as argument.
diff --git a/nptl/Makefile b/nptl/Makefile
index 140f06318f..aaca0a4700 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -245,7 +245,7 @@ tests = tst-typesizes \
 	tst-basic7 \
 	tst-kill1 tst-kill2 tst-kill3 tst-kill4 tst-kill5 tst-kill6 \
 	tst-raise1 \
-	tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 tst-join6 \
+	tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 tst-join6 tst-join7 \
 	tst-detach1 \
 	tst-eintr1 tst-eintr2 tst-eintr3 tst-eintr4 tst-eintr5 \
 	tst-tsd1 tst-tsd2 tst-tsd3 tst-tsd4 tst-tsd5 tst-tsd6 \
@@ -327,7 +327,8 @@ endif
 modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \
 		tst-tls5mod tst-tls5moda tst-tls5modb tst-tls5modc \
 		tst-tls5modd tst-tls5mode tst-tls5modf tst-stack4mod \
-		tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod
+		tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod \
+		tst-join7mod
 extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) tst-cleanup4aux.o
 test-extras += $(modules-names) tst-cleanup4aux
 test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names)))
@@ -532,6 +533,11 @@ $(objpfx)tst-tls6.out: tst-tls6.sh $(objpfx)tst-tls5 \
 	$(evaluate-test)
 endif
 
+$(objpfx)tst-join7: $(libdl) $(shared-thread-library)
+$(objpfx)tst-join7.out: $(objpfx)tst-join7mod.so
+$(objpfx)tst-join7mod.so: $(shared-thread-library)
+LDFLAGS-tst-join7mod.so = -Wl,-soname,tst-join7mod.so
+
 $(objpfx)tst-dlsym1: $(libdl) $(shared-thread-library)
 
 $(objpfx)tst-fini1: $(shared-thread-library) $(objpfx)tst-fini1mod.so
diff --git a/nptl/tst-join7.c b/nptl/tst-join7.c
new file mode 100644
index 0000000000..439d0fc9bb
--- /dev/null
+++ b/nptl/tst-join7.c
@@ -0,0 +1,46 @@
+/* Verify that TLS access in separate thread in a dlopened library does not
+   deadlock.
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <dlfcn.h>
+
+/* 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <pthread.h>
+#include <atomic.h>
+
+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");
+}