diff options
author | Paul Pluzhnikov <ppluzhnikov@google.com> | 2014-01-11 16:34:15 -0800 |
---|---|---|
committer | Paul Pluzhnikov <ppluzhnikov@google.com> | 2014-01-11 16:34:15 -0800 |
commit | 2112e176757483dd25a7cf38ead63a237bf5e52e (patch) | |
tree | 80f02dd662d0da8f1fe40e96a2965aeb9ac23cba | |
parent | 5d43293bacbdc09e0e060cfd002d2fb34b3facd3 (diff) | |
download | glibc-2112e176757483dd25a7cf38ead63a237bf5e52e.tar.gz glibc-2112e176757483dd25a7cf38ead63a237bf5e52e.tar.xz glibc-2112e176757483dd25a7cf38ead63a237bf5e52e.zip |
Fix a race in tst-tls7, which caused crashes on ppc32.
-rw-r--r-- | nptl/ChangeLog | 6 | ||||
-rw-r--r-- | nptl/tst-tls7.c | 27 | ||||
-rw-r--r-- | nptl/tst-tls7mod.c | 3 |
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); } |