regress/sys/kern/kqueue/kqueue-process (kqueue-test -P) is a test to
receive process-related events (fork/exec/exit).  This test forks a
child, then forks a child-child from child.  But parent checks only
child's exit.  This has worked because scheduler happens to run child-child
much later.

Don't rely on that racy condition but check child-child events too.
Found by Valgrind (by luck).

Index: kqueue-process.c
===================================================================
RCS file: /cvs/src/regress/sys/kern/kqueue/kqueue-process.c,v
retrieving revision 1.6
diff -u -p -r1.6 kqueue-process.c
--- kqueue-process.c    2 Aug 2015 00:47:25 -0000       1.6
+++ kqueue-process.c    2 Aug 2015 01:01:31 -0000
@@ -105,19 +105,24 @@ do_process(void)
        kill(pid2, SIGUSR1);    /* sync 2.1 */
        kill(pid, SIGUSR1);     /* sync 2 */
 
+       /* Wait for child's exit. */
        if (wait(&status) < 0)
                err(1, "wait");
+       /* Wait for child-child's exec/exit to receive two events at once. */
+       sleep(1);
 
-       for (i = 0; i < 1; i++) {
-               /* make sure we get an exit note */
+       for (i = 0; i < 2; i++) {
                ASS(kevent(kq, NULL, 0, &ke, 1, &ts) == 1,
                    warnx("didn't receive event"));
                ASSX(ke.filter == EVFILT_PROC);
                switch (ke.fflags) {
                case NOTE_EXIT:
-                       didchild = 1;
                        ASSX((pid_t)ke.ident == pid);
-                       fprintf(stderr, "exit %d\n", pid);
+                       fprintf(stderr, "child exit %d\n", pid);
+                       break;
+               case NOTE_EXEC | NOTE_EXIT:
+                       ASSX((pid_t)ke.ident == pid2);
+                       fprintf(stderr, "child-child exec/exit %d\n", pid2);
                        break;
                default:
                        errx(1, "kevent returned weird event 0x%x pid %d",

Reply via email to