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 + + * tst-tls7.c (action): New function. + (do_test): Call it. + * tst-tls7mod.c (action): Move sem_post to caller. + 2014-01-03 Andrew Hunter * 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 +#include #include #include #include @@ -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); }