diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-09-10 15:46:08 +0200 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-09-10 15:46:08 +0200 |
commit | 4b8fa99ea518f12599d970ff7654245d0e2a208e (patch) | |
tree | 5fd58a4aa8fbcd44024a010c417b253ce92e7c81 | |
parent | 2096649053cf720258d66095af0c54453727e841 (diff) |
lib/drmtest: create helpers for forking helper threads
The upshot is that we can share the logic to make sure the helpers
are all properly stoved again in a 2nd step.
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r-- | lib/drmtest.c | 80 | ||||
-rw-r--r-- | lib/drmtest.h | 9 |
2 files changed, 61 insertions, 28 deletions
diff --git a/lib/drmtest.c b/lib/drmtest.c index f7f230b0..401dccb5 100644 --- a/lib/drmtest.c +++ b/lib/drmtest.c @@ -591,7 +591,7 @@ static bool igt_only_list_subtests(void); static int exit_handler_count; -static pid_t signal_helper = -1; +static struct igt_helper_process signal_helper; long long int sig_stat; static void __attribute__((noreturn)) signal_helper_process(pid_t pid) { @@ -615,47 +615,25 @@ static void signal_helper_exit_handler(int sig) void igt_fork_signal_helper(void) { - pid_t pid; - sighandler_t oldsig; if (igt_only_list_subtests()) return; - igt_install_exit_handler(signal_helper_exit_handler); + printf("installing signal helper\n"); signal(SIGUSR1, sig_handler); - oldsig = signal(SIGQUIT, SIG_DFL); - pid = fork(); - if (pid == 0) { - exit_handler_count = 0; + igt_install_exit_handler(signal_helper_exit_handler); + igt_fork_helper(&signal_helper) { signal_helper_process(getppid()); - return; } - signal(SIGQUIT, oldsig); - - signal_helper = pid; } void igt_stop_signal_helper(void) { - int exitcode; - - if (signal_helper != -1) { - kill(signal_helper, SIGQUIT); - wait(&exitcode); - - signal_helper = -1; - } else - return; - -#if 0 - if (sig_stat) - fprintf(stdout, "signal handler called %llu times\n", sig_stat); -#endif + igt_stop_helper(&signal_helper); sig_stat = 0; - signal_helper = -1; } /* subtests helpers */ @@ -974,6 +952,53 @@ void igt_exit(void) exit(77); } +static int helper_process_count; + +bool __igt_fork_helper(struct igt_helper_process *proc) +{ + pid_t pid; + sighandler_t oldsig; + + assert(!proc->running); + + oldsig = signal(SIGQUIT, SIG_DFL); + switch (pid = fork()) { + case -1: + igt_assert(0); + case 0: + exit_handler_count = 0; + + return true; + default: + signal(SIGQUIT, oldsig); + proc->running = true; + proc->pid = pid; + helper_process_count++; + + return false; + } + +} + +/** + * igt_waitchildren - wait for all children forked with igt_fork + * + * The magic here is that exit codes from children will be correctly propagated + */ +void igt_stop_helper(struct igt_helper_process *proc) +{ + int status; + + assert(proc->running); + + kill(proc->pid, SIGQUIT); + waitpid(proc->pid, &status, 0); + + proc->running = false; + + helper_process_count--; +} + bool __igt_fork(void) { assert(!test_with_subtests || in_subtest); @@ -1673,7 +1698,6 @@ static void call_exit_handlers(int sig) int i; if (!exit_handler_count) { - fprintf(stderr, "no exit handlers?\n"); return; } diff --git a/lib/drmtest.h b/lib/drmtest.h index f55825e7..f6efe5d4 100644 --- a/lib/drmtest.h +++ b/lib/drmtest.h @@ -221,6 +221,15 @@ bool __igt_fork(void); for (; __igt_fork(); exit(0)) void igt_waitchildren(void); +struct igt_helper_process { + bool running; + pid_t pid; +}; +bool __igt_fork_helper(struct igt_helper_process *proc); +void igt_stop_helper(struct igt_helper_process *proc); +#define igt_fork_helper(proc) \ + for (; __igt_fork_helper(proc); exit(0)) + /* check functions which auto-skip tests by calling igt_skip() */ void gem_require_caching(int fd); static inline void gem_require_ring(int fd, int ring_id) |