00db10
commit a3e5b4feeb54cb92657ec2bc6d9be1fcef9e8575
00db10
Author: Paul E. Murphy <murphyp@linux.vnet.ibm.com>
00db10
Date:   Mon Jan 11 17:24:04 2016 -0500
00db10
00db10
    Fix race in tst-mqueue5
00db10
    
00db10
    The check is done on line 117 by a thread spawned
00db10
    from do_child(), forked from do_test().  This test
00db10
    generates a signal in the forked process.
00db10
    
00db10
    Either thread may handle the signal, and on ppc,
00db10
    it happens to be done on do_child, on the thread
00db10
    which is not doing the check on line 117.
00db10
    
00db10
    This exposes a race condition whereby the test
00db10
    incorrectly fails as the signal is caught during
00db10
    or after the check.
00db10
    
00db10
    This is mitigated by ensuring the signal is blocked
00db10
    in the child thread while thread is running.
00db10
00db10
 2016-01-15  Martin Sebor  <msebor@redhat.com>
00db10
 
00db10
 	[BZ #19432]
00db10
diff --git a/rt/tst-mqueue5.c b/rt/tst-mqueue5.c
00db10
index aa74fa3..25042bc 100644
00db10
--- a/rt/tst-mqueue5.c
00db10
+++ b/rt/tst-mqueue5.c
00db10
@@ -116,7 +116,7 @@ thr (void *arg)
00db10
 
00db10
   if (rtmin_cnt != 2)
00db10
     {
00db10
-      puts ("SIGRTMIN signal in child did not arrive");
00db10
+      puts ("SIGRTMIN signal in thread did not arrive");
00db10
       result = 1;
00db10
     }
00db10
   else if (rtmin_pid != getppid ()
00db10
@@ -403,6 +403,16 @@ do_child (const char *name, pthread_barrier_t *b2, pthread_barrier_t *b3,
00db10
       result = 1;
00db10
     }
00db10
 
00db10
+  /* Ensure the thr thread gets the signal, not us.  */
00db10
+  sigset_t set;
00db10
+  sigemptyset (&set);
00db10
+  sigaddset (&set, SIGRTMIN);
00db10
+  if (pthread_sigmask (SIG_BLOCK, &set, NULL))
00db10
+    {
00db10
+      printf ("Failed to block SIGRTMIN in child: %m\n");
00db10
+      result = 1;
00db10
+    }
00db10
+
00db10
   (void) pthread_barrier_wait (b2);
00db10
 
00db10
   /* Parent calls mqsend (q), which should wake up mqrecv (q)
00db10
@@ -514,7 +524,14 @@ do_child (const char *name, pthread_barrier_t *b2, pthread_barrier_t *b3,
00db10
       result = 1;
00db10
     }
00db10
 
00db10
- void *thr_ret;
00db10
+  /* Reenable test signals before cleaning up the thread.  */
00db10
+  if (pthread_sigmask (SIG_UNBLOCK, &set, NULL))
00db10
+    {
00db10
+      printf ("Failed to unblock SIGRTMIN in child: %m\n");
00db10
+      result = 1;
00db10
+    }
00db10
+
00db10
+  void *thr_ret;
00db10
   ret = pthread_join (th, &thr_ret);
00db10
   if (ret)
00db10
     {