This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: posix/tst-waitid.c possible race condition on Linux
- From: Roland McGrath <roland at hack dot frob dot com>
- To: Olivier Langlois <olivier at trillion01 dot com>
- Cc: libc-alpha at sourceware dot org
- Date: Wed, 12 Jun 2013 17:03:30 -0700 (PDT)
- Subject: Re: posix/tst-waitid.c possible race condition on Linux
- References: <1371011970 dot 749 dot 30 dot camel at Wailaba2>
I think the test was racy. A change that will probably fix it is on the
branch roland/tst-waitid and the patch is below, but I haven't been able to
test it yet.
Thanks,
Roland
2013-06-12 Roland McGrath <roland@hack.frob.com>
* posix/tst-waitid.c (do_test): Distinguish different instances of
stopped/continued in CHECK_SIGCHLD uses. Insert a delay between
sending SIGSTOP and calling waitpid to ensure SIGCHLD gets delivered
before entering the kernel for waitpid.
--- a/posix/tst-waitid.c
+++ b/posix/tst-waitid.c
@@ -145,7 +145,7 @@ do_test (int argc, char *argv[])
/* Give the child a chance to stop. */
sleep (3);
- CHECK_SIGCHLD ("stopped", CLD_STOPPED, SIGSTOP);
+ CHECK_SIGCHLD ("stopped (before waitid)", CLD_STOPPED, SIGSTOP);
/* Now try a wait that should not succeed. */
siginfo_t info;
@@ -227,7 +227,7 @@ do_test (int argc, char *argv[])
expecting_sigchld = 0;
}
else
- CHECK_SIGCHLD ("continued", CLD_CONTINUED, SIGCONT);
+ CHECK_SIGCHLD ("continued (before waitid)", CLD_CONTINUED, SIGCONT);
info.si_signo = 0; /* A successful call sets it to SIGCHLD. */
info.si_pid = -1;
@@ -336,6 +336,13 @@ do_test (int argc, char *argv[])
printf ("kill (%d, SIGSTOP): %m\n", pid);
RETURN (EXIT_FAILURE);
}
+
+ /* Give the child a chance to stop. The waitpid call below will block
+ until it has stopped, but if we are real quick and enter the waitpid
+ system call before the SIGCHLD has been generated, then it will be
+ discarded and never delivered. */
+ sleep (3);
+
pid_t wpid = waitpid (pid, &fail, WUNTRACED);
if (wpid < 0)
{
@@ -354,7 +361,7 @@ do_test (int argc, char *argv[])
printf ("waitpid WUNTRACED on stopped: status %x\n", fail);
RETURN (EXIT_FAILURE);
}
- CHECK_SIGCHLD ("stopped", CLD_STOPPED, SIGSTOP);
+ CHECK_SIGCHLD ("stopped (after waitpid)", CLD_STOPPED, SIGSTOP);
expecting_sigchld = 1;
if (kill (pid, SIGCONT) != 0)
@@ -372,7 +379,7 @@ do_test (int argc, char *argv[])
expecting_sigchld = 0;
}
else
- CHECK_SIGCHLD ("continued", CLD_CONTINUED, SIGCONT);
+ CHECK_SIGCHLD ("continued (before waitpid)", CLD_CONTINUED, SIGCONT);
wpid = waitpid (pid, &fail, WCONTINUED);
if (wpid < 0)