fork() is a pretty thing in a multithreaded program, it's essentially as bad as handling signals: When we fork the memory snapshot we can interrupts all other threads at any place, including while they're holding mutexes and other fun stuff. libc itself has some internal fork handlers to clear caches and make sure locks stay in a safe place (we've had plenty of fun with e.g. the pid/tid caches when a signal happens too fast). I want to put dmesg capture into igt, into a separate thread (so that dmesg capture nicely interleaves what the test is doing, +/- races), and stuff all the dmesg output into the igt logger. Which means we need to make sure that the log_buffer_mutex is in a predictable state. Since we have 2 calls to fork() extract a little helper for this. v2: Stop using fflush(NULL) - somehow this manages to hit a bug in libc when using a FILE in a separate thread (for capturing dmesg). Instead explicitly flush stderr and stdout only. Signed-off-by: Daniel Vetter <daniel.vetter@xxxxxxxxx> --- lib/igt_core.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/lib/igt_core.c b/lib/igt_core.c index 558a538d35e8..8e7f0da8a44b 100644 --- a/lib/igt_core.c +++ b/lib/igt_core.c @@ -1518,6 +1518,21 @@ static void fork_helper_exit_handler(int sig) assert(helper_process_count == 0); } +static pid_t __igt_fork_wrapper(void) +{ + pid_t ret; + + /* ensure any buffers are flushed before fork */ + fflush(stdout); + fflush(stderr); + + pthread_mutex_lock(&log_buffer_mutex); + ret = fork(); + pthread_mutex_unlock(&log_buffer_mutex); + + return ret; +} + bool __igt_fork_helper(struct igt_helper_process *proc) { pid_t pid; @@ -1540,10 +1555,7 @@ bool __igt_fork_helper(struct igt_helper_process *proc) tmp_count = exit_handler_count; exit_handler_count = 0; - /* ensure any buffers are flushed before fork */ - fflush(NULL); - - switch (pid = fork()) { + switch (pid = __igt_fork_wrapper()) { case -1: exit_handler_count = tmp_count; igt_assert(0); @@ -1642,10 +1654,7 @@ bool __igt_fork(void) igt_assert(test_children); } - /* ensure any buffers are flushed before fork */ - fflush(NULL); - - switch (test_children[num_test_children++] = fork()) { + switch (test_children[num_test_children++] = __igt_fork_wrapper()) { case -1: igt_assert(0); case 0: -- 2.14.3 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx