summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2013-09-10 15:46:08 +0200
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-09-10 15:46:08 +0200
commit4b8fa99ea518f12599d970ff7654245d0e2a208e (patch)
tree5fd58a4aa8fbcd44024a010c417b253ce92e7c81
parent2096649053cf720258d66095af0c54453727e841 (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.c80
-rw-r--r--lib/drmtest.h9
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)