From a031a1bf93b828585e7147f06145fc5030814547 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 13 Sep 2013 16:43:22 +0200 Subject: [PATCH] lib/drmtest: ducttape over fork race Whatever the reason (and I've thought there isn't one) if we fork and kill right away the child seems to not reliably die. We can work around this little race by forcing the default SIGQUIT handler. This should break anything since we reset our atexit handling anyway, so if the helper needs any atexit handling the special signal helpers will be reinstated. Note that inserting sufficient amounts of printf between the fork and kill makes this unnecessary. While add it also add the retry loop for the waitpid call, in case there's another guy constantly interrupting us. Signed-off-by: Daniel Vetter --- lib/drmtest.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/drmtest.c b/lib/drmtest.c index 1ba8cad4..a3ff0d6f 100644 --- a/lib/drmtest.c +++ b/lib/drmtest.c @@ -981,6 +981,7 @@ static void fork_helper_exit_handler(int sig) bool __igt_fork_helper(struct igt_helper_process *proc) { pid_t pid; + sighandler_t oldsig; int id; assert(!proc->running); @@ -991,6 +992,13 @@ bool __igt_fork_helper(struct igt_helper_process *proc) igt_install_exit_handler(fork_helper_exit_handler); + /* + * XXX: There's a race between fork and the subsequent kill in + * igt_stop_signal_helper if we don't ovewrite the SIGQUIT handler. Note + * that inserting sufficient amounts of printf or other delays makes + * this unnecessary. + */ + oldsig = signal(SIGQUIT, SIG_DFL); switch (pid = fork()) { case -1: igt_assert(0); @@ -1000,6 +1008,8 @@ bool __igt_fork_helper(struct igt_helper_process *proc) return true; default: + signal(SIGQUIT, oldsig); + proc->running = true; proc->pid = pid; proc->id = id; @@ -1023,7 +1033,9 @@ void igt_stop_helper(struct igt_helper_process *proc) assert(proc->running); assert(kill(proc->pid, SIGQUIT) == 0); - waitpid(proc->pid, &status, 0); + while (waitpid(proc->pid, &status, 0) == -1 && + errno == -EINTR) + ; proc->running = false;