Fix a race in tst-tls7, which caused crashes on ppc32.
authorPaul Pluzhnikov <ppluzhnikov@google.com>
Sun, 12 Jan 2014 00:34:15 +0000 (16:34 -0800)
committerPaul Pluzhnikov <ppluzhnikov@google.com>
Sun, 12 Jan 2014 00:34:15 +0000 (16:34 -0800)
nptl/ChangeLog
nptl/tst-tls7.c
nptl/tst-tls7mod.c

index 3c7675e..149509e 100644 (file)
@@ -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.
index 3bb3f7d..583d5b4 100644 (file)
@@ -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");
index aff29b9..da5af56 100644 (file)
@@ -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);
 }