Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix race in tst-mqueue5
The check is done on line 117 by a thread spawned
from do_child(), forked from do_test().  This test
generates a signal in the forked process.

Either thread may handle the signal, and on ppc,
it happens to be done on do_child, on the thread
which is not doing the check on line 117.

This exposes a race condition whereby the test
incorrectly fails as the signal is caught during
or after the check.

This is mitigated by ensuring the signal is blocked
in the child thread while thread is running.
  • Loading branch information
Paul E. Murphy authored and Tulio Magno Quites Machado Filho committed Jan 15, 2016
1 parent 692de4b commit a3e5b4f
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 2 deletions.
5 changes: 5 additions & 0 deletions ChangeLog
@@ -1,3 +1,8 @@
2016-01-15 Paul E. Murphy <murphyp@linux.vnet.ibm.com>

* rt/tst-mqueue5.c (thr): Cleanup misleading comment.
(do_child): Mask SIGRTMIN while thr is running.

2016-01-15 Martin Sebor <msebor@redhat.com>

[BZ #19432]
Expand Down
21 changes: 19 additions & 2 deletions rt/tst-mqueue5.c
Expand Up @@ -116,7 +116,7 @@ thr (void *arg)

if (rtmin_cnt != 2)
{
puts ("SIGRTMIN signal in child did not arrive");
puts ("SIGRTMIN signal in thread did not arrive");
result = 1;
}
else if (rtmin_pid != getppid ()
Expand Down Expand Up @@ -403,6 +403,16 @@ do_child (const char *name, pthread_barrier_t *b2, pthread_barrier_t *b3,
result = 1;
}

/* Ensure the thr thread gets the signal, not us. */
sigset_t set;
sigemptyset (&set);
sigaddset (&set, SIGRTMIN);
if (pthread_sigmask (SIG_BLOCK, &set, NULL))
{
printf ("Failed to block SIGRTMIN in child: %m\n");
result = 1;
}

(void) pthread_barrier_wait (b2);

/* Parent calls mqsend (q), which should wake up mqrecv (q)
Expand Down Expand Up @@ -514,7 +524,14 @@ do_child (const char *name, pthread_barrier_t *b2, pthread_barrier_t *b3,
result = 1;
}

void *thr_ret;
/* Reenable test signals before cleaning up the thread. */
if (pthread_sigmask (SIG_UNBLOCK, &set, NULL))
{
printf ("Failed to unblock SIGRTMIN in child: %m\n");
result = 1;
}

void *thr_ret;
ret = pthread_join (th, &thr_ret);
if (ret)
{
Expand Down

0 comments on commit a3e5b4f

Please sign in to comment.