aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Pluzhnikov <ppluzhnikov@google.com>2014-01-11 16:34:15 -0800
committerPaul Pluzhnikov <ppluzhnikov@google.com>2014-01-11 16:34:15 -0800
commit2112e176757483dd25a7cf38ead63a237bf5e52e (patch)
tree80f02dd662d0da8f1fe40e96a2965aeb9ac23cba
parent5d43293bacbdc09e0e060cfd002d2fb34b3facd3 (diff)
downloadglibc-2112e176757483dd25a7cf38ead63a237bf5e52e.tar
glibc-2112e176757483dd25a7cf38ead63a237bf5e52e.tar.gz
glibc-2112e176757483dd25a7cf38ead63a237bf5e52e.tar.bz2
glibc-2112e176757483dd25a7cf38ead63a237bf5e52e.zip
Fix a race in tst-tls7, which caused crashes on ppc32.
-rw-r--r--nptl/ChangeLog6
-rw-r--r--nptl/tst-tls7.c27
-rw-r--r--nptl/tst-tls7mod.c3
3 files changed, 31 insertions, 5 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 3c7675e591..149509e8b1 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,9 @@
+2014-01-11 Paul Pluzhnikov <ppluzhnikov@google.com>
+
+ * tst-tls7.c (action): New function.
+ (do_test): Call it.
+ * tst-tls7mod.c (action): Move sem_post to caller.
+
2014-01-03 Andrew Hunter <ahh@google.com>
* nptl/Makefile (tst-tls7): New test.
diff --git a/nptl/tst-tls7.c b/nptl/tst-tls7.c
index 3bb3f7db6b..583d5b4620 100644
--- a/nptl/tst-tls7.c
+++ b/nptl/tst-tls7.c
@@ -19,6 +19,8 @@
/* This test checks that TLS in a dlopened object works when first accessed
from a signal handler. */
+#include <assert.h>
+#include <atomic.h>
#include <dlfcn.h>
#include <pthread.h>
#include <semaphore.h>
@@ -39,6 +41,23 @@ spin (void *ignored)
return NULL;
}
+static void (*tls7mod_action) (int, siginfo_t *, void *);
+
+static void
+action (int signo, siginfo_t *info, void *ignored)
+{
+ sem_t *sem = info->si_value.sival_ptr;
+
+ atomic_read_barrier ();
+ assert (tls7mod_action != NULL);
+ (*tls7mod_action) (signo, info, ignored);
+
+ /* This sem_post may trigger dlclose, which will invalidate tls7mod_action.
+ It is important to do that only after tls7mod_action is no longer
+ active. */
+ sem_post (sem);
+}
+
int
do_test (void)
{
@@ -63,12 +82,13 @@ do_test (void)
exit (1);
}
- void (*action) (int, siginfo_t *, void *) = dlsym (h, "action");
- if (action == NULL)
+ tls7mod_action = dlsym (h, "action");
+ if (tls7mod_action == NULL)
{
puts ("dlsym for action failed");
exit (1);
}
+ atomic_write_barrier ();
struct sigaction sa;
sa.sa_sigaction = action;
@@ -105,6 +125,9 @@ do_test (void)
}
}
+ /* Paranoia. */
+ tls7mod_action = NULL;
+
if (dlclose (h))
{
puts ("dlclose failed");
diff --git a/nptl/tst-tls7mod.c b/nptl/tst-tls7mod.c
index aff29b9d6c..da5af56370 100644
--- a/nptl/tst-tls7mod.c
+++ b/nptl/tst-tls7mod.c
@@ -29,7 +29,6 @@ static __thread intptr_t tls_data = 0xdeadbeef;
void
action (int signo, siginfo_t *info, void *ignored)
{
- sem_t *sem = info->si_value.sival_ptr;
if (tls_data != 0xdeadbeef)
{
write (STDOUT_FILENO, "wrong TLS value\n", 17);
@@ -38,6 +37,4 @@ action (int signo, siginfo_t *info, void *ignored)
/* arbitrary choice, just write something unique-ish. */
tls_data = (intptr_t) info;
-
- sem_post (sem);
}