From 1e522b7ed1a0747f70c841dcf5b973f4d8de556d Mon Sep 17 00:00:00 2001 From: visa Date: Fri, 3 Aug 2018 15:19:44 +0000 Subject: [PATCH] Improve synchronization between the parent and children. This fixes a spurious test failure spotted by anton@ and eliminates sleeping in the test. Feedback and OK anton@ --- regress/sys/kern/kqueue/kqueue-process.c | 62 +++++++++++++----------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/regress/sys/kern/kqueue/kqueue-process.c b/regress/sys/kern/kqueue/kqueue-process.c index dd3ae9b536c..79fdfad2d77 100644 --- a/regress/sys/kern/kqueue/kqueue-process.c +++ b/regress/sys/kern/kqueue/kqueue-process.c @@ -1,15 +1,15 @@ -/* $OpenBSD: kqueue-process.c,v 1.12 2016/09/20 23:05:27 bluhm Exp $ */ +/* $OpenBSD: kqueue-process.c,v 1.13 2018/08/03 15:19:44 visa Exp $ */ /* * Written by Artur Grabowski 2002 Public Domain */ #include #include +#include #include #include #include -#include #include #include #include @@ -18,21 +18,19 @@ static int process_child(void); -static void -usr1handler(int signum) -{ - /* nada */ -} +static int pfd1[2]; +static int pfd2[2]; int do_process(void) { struct kevent ke; + struct timespec ts; int kq, status; pid_t pid, pid2; int didfork, didchild; int i; - struct timespec ts; + char ch = 0; /* * Timeout in case something doesn't work. @@ -43,11 +41,11 @@ do_process(void) ASS((kq = kqueue()) >= 0, warn("kqueue")); - /* - * Install a signal handler so that we can use pause() to synchronize - * with the child with the parent. - */ - signal(SIGUSR1, usr1handler); + /* Open pipes for synchronizing the children with the parent. */ + if (pipe(pfd1) == -1) + err(1, "pipe 1"); + if (pipe(pfd2) == -1) + err(1, "pipe 2"); switch ((pid = fork())) { case -1: @@ -56,8 +54,6 @@ do_process(void) _exit(process_child()); } - sleep(2); /* wait for child to settle down. */ - EV_SET(&ke, pid, EVFILT_PROC, EV_ADD|EV_ENABLE|EV_CLEAR, NOTE_EXIT|NOTE_FORK|NOTE_EXEC|NOTE_TRACK, 0, NULL); ASS(kevent(kq, &ke, 1, NULL, 0, NULL) == 0, @@ -71,7 +67,8 @@ do_process(void) ASS(errno == ESRCH, warn("register bogus pid on kqueue returned wrong error")); - kill(pid, SIGUSR1); /* sync 1 */ + ASS(write(pfd1[1], &ch, 1) == 1, + warn("write sync 1")); didfork = didchild = 0; @@ -107,14 +104,18 @@ do_process(void) ASSX(didchild == 1); ASSX(didfork == 1); - kill(pid2, SIGUSR1); /* sync 2.1 */ - kill(pid, SIGUSR1); /* sync 2 */ + ASS(write(pfd2[1], &ch, 1) == 1, + warn("write sync 2.1")); + ASS(write(pfd1[1], &ch, 1) == 1, + warn("write sync 2")); - /* Wait for child's exit. */ + /* + * Wait for child's exit. It also implies child-child has exited. + * This should ensure that NOTE_EXIT has been posted for both children. + * Child-child's events should get aggregated. + */ 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 < 2; i++) { ASS(kevent(kq, NULL, 0, &ke, 1, &ts) == 1, @@ -145,23 +146,30 @@ do_process(void) static int process_child(void) { - signal(SIGCHLD, SIG_IGN); /* ignore our children. */ + int status; + char ch; - pause(); + ASS(read(pfd1[0], &ch, 1) == 1, + warn("read sync 1")); /* fork and see if tracking works. */ switch (fork()) { case -1: err(1, "fork"); case 0: - /* sync 2.1 */ - pause(); + ASS(read(pfd2[0], &ch, 1) == 1, + warn("read sync 2.1")); execl("/usr/bin/true", "true", (char *)NULL); err(1, "execl(true)"); } - /* sync 2 */ - pause(); + ASS(read(pfd1[0], &ch, 1) == 1, + warn("read sync 2")); + + if (wait(&status) < 0) + err(1, "wait 2"); + if (!WIFEXITED(status)) + errx(1, "child-child didn't exit?"); return 0; } -- 2.20.1