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>
This commit is contained in:
Daniel Vetter 2013-09-10 15:46:08 +02:00
parent 2096649053
commit edd723457c
2 changed files with 60 additions and 29 deletions

View File

@ -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,23 @@ 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;
signal(SIGUSR1, sig_handler);
igt_install_exit_handler(signal_helper_exit_handler);
signal(SIGUSR1, sig_handler);
oldsig = signal(SIGQUIT, SIG_DFL);
pid = fork();
if (pid == 0) {
exit_handler_count = 0;
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 +950,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 +1696,6 @@ static void call_exit_handlers(int sig)
int i;
if (!exit_handler_count) {
fprintf(stderr, "no exit handlers?\n");
return;
}

View File

@ -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)