The clone() system call with a larger executable (like /bin/sh) may have difficulty to make progress on some platforms if interrupted frequently. So suspend the signal helper process for the duration of the syscall. This is needed to solve an actual problem by the next patch. Cc: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> Cc: Daniel Vetter <daniel.vetter@xxxxxxxxx> Signed-off-by: Imre Deak <imre.deak@xxxxxxxxx> --- lib/igt_aux.c | 38 ++++++++++++++++++++++++++++++++++++++ lib/igt_aux.h | 2 ++ lib/igt_core.c | 9 +++++++++ 3 files changed, 49 insertions(+) diff --git a/lib/igt_aux.c b/lib/igt_aux.c index fa6594c3..36dfab43 100644 --- a/lib/igt_aux.c +++ b/lib/igt_aux.c @@ -350,6 +350,44 @@ void igt_stop_signal_helper(void) sig_stat = 0; } +/** + * igt_suspend_signal_helper: + * + * Suspends the child process spawned with igt_fork_signal_helper(). + * + * This should be called before code that has difficulty to make progress if + * interrupted frequently, like the clone() syscall spawning a large + * executable. + */ +void igt_suspend_signal_helper(void) +{ + int status; + + if (!signal_helper.running) + return; + + kill(signal_helper.pid, SIGSTOP); + while (waitpid(signal_helper.pid, &status, WUNTRACED) == -1 && + errno == EINTR) + ; +} + +/** + * igt_suspend_signal_helper: + * + * Resumes the child process spawned with igt_fork_signal_helper(). + * + * This should be paired with igt_suspend_signal_helper() and called after the + * problematic code sensitive to signals. + */ +void igt_resume_signal_helper(void) +{ + if (!signal_helper.running) + return; + + kill(signal_helper.pid, SIGCONT); +} + static struct igt_helper_process shrink_helper; static void __attribute__((noreturn)) shrink_helper_process(int fd, pid_t pid) { diff --git a/lib/igt_aux.h b/lib/igt_aux.h index 499a1679..688ad1b8 100644 --- a/lib/igt_aux.h +++ b/lib/igt_aux.h @@ -55,6 +55,8 @@ extern int num_trash_bos; /* generally useful helpers */ void igt_fork_signal_helper(void); void igt_stop_signal_helper(void); +void igt_suspend_signal_helper(void); +void igt_resume_signal_helper(void); void igt_fork_shrink_helper(int fd); void igt_stop_shrink_helper(void); diff --git a/lib/igt_core.c b/lib/igt_core.c index 950ea9b0..ea4b5fa6 100644 --- a/lib/igt_core.c +++ b/lib/igt_core.c @@ -2282,6 +2282,13 @@ int igt_system(const char *command) if (pipe(errpipe) < 0) goto err; + /* + * The clone() system call forking a large executable has difficulty + * to make progress if interrupted too frequently, so suspend it for + * the time of the syscall. + */ + igt_suspend_signal_helper(); + igt_fork_helper(&process) { close(outpipe[0]); close(errpipe[0]); @@ -2298,6 +2305,8 @@ int igt_system(const char *command) exit(EXIT_FAILURE); } + igt_resume_signal_helper(); + close(outpipe[1]); close(errpipe[1]); -- 2.13.2 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx