From 2423b6c04e54792adc42b7d477861d9ffb87fdc3 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 5 Feb 2014 13:48:26 +0200 Subject: [PATCH] lib/drmtest: fix hang in quiescent_gpu_at_exit due to signal-unsafe asprintf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I got kms_flip in hung state with the backtrace below, while the parent process waiting for the signal helper to exit. It was quite easy to reproduce the bug by running kms_flip --run-subtest=flip-vs-dpms-off-vs-modeset With the change I couldn't reproduce it. TODO: audit/fix other signal handlers with signal-unsafe functions 0  0x00007f9a1362018b in ?? () from /lib/x86_64-linux-gnu/libc.so.6 1  0x00007f9a1359df81 in ?? () from /lib/x86_64-linux-gnu/libc.so.6 2  0x00007f9a1359b6cf in ?? () from /lib/x86_64-linux-gnu/libc.so.6 3  0x00007f9a13628eb6 in __vasprintf_chk () from /lib/x86_64-linux-gnu/libc.so.6 4  0x00007f9a13628e72 in __asprintf_chk () from /lib/x86_64-linux-gnu/libc.so.6 5  0x000000000040a4a2 in asprintf (__fmt=0x417441 "/dev/dri/card%u", __ptr=0x7fff1a972c08)     at /usr/include/x86_64-linux-gnu/bits/stdio2.h:178 6  drm_get_card () at drmtest.c:190 7  0x000000000040a54a in __drm_open_any () at drmtest.c:229 8  0x000000000040a846 in quiescent_gpu_at_exit (sig=) at drmtest.c:281 9  0x0000000000408759 in call_exit_handlers (sig=3) at drmtest.c:1519 10 fatal_sig_handler (sig=3) at drmtest.c:1543 11 12 0x00007f9a13596770 in ?? () from /lib/x86_64-linux-gnu/libc.so.6 13 0x00007f9a135d8f3f in fork () from /lib/x86_64-linux-gnu/libc.so.6 14 0x000000000040b3af in __igt_fork_helper (proc=0x61d8cc ) at drmtest.c:1199 15 0x000000000040b4ce in igt_fork_signal_helper () at drmtest.c:751 16 0x0000000000404167 in main (argc=, argv=) at kms_flip.c:1533 v2: - can't use snprintf as that's also signal-unsafe, so just use a dup'ed fd (Chris,Daniel) Signed-off-by: Imre Deak --- lib/drmtest.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/lib/drmtest.c b/lib/drmtest.c index f7262d7b..02496c5d 100644 --- a/lib/drmtest.c +++ b/lib/drmtest.c @@ -274,26 +274,27 @@ static int __drm_open_any_render(void) return fd; } +static int at_exit_drm_fd = -1; +static int at_exit_drm_render_fd = -1; + static void quiescent_gpu_at_exit(int sig) { - int fd; + if (at_exit_drm_fd < 0) + return; - fd = __drm_open_any(); - if (fd >= 0) { - gem_quiescent_gpu(fd); - close(fd); - } + gem_quiescent_gpu(at_exit_drm_fd); + close(at_exit_drm_fd); + at_exit_drm_fd = -1; } static void quiescent_gpu_at_exit_render(int sig) { - int fd; + if (at_exit_drm_render_fd < 0) + return; - fd = __drm_open_any_render(); - if (fd >= 0) { - gem_quiescent_gpu(fd); - close(fd); - } + gem_quiescent_gpu(at_exit_drm_render_fd); + close(at_exit_drm_render_fd); + at_exit_drm_render_fd = -1; } int drm_open_any(void) @@ -307,6 +308,7 @@ int drm_open_any(void) return fd; gem_quiescent_gpu(fd); + at_exit_drm_fd = dup(fd); igt_install_exit_handler(quiescent_gpu_at_exit); return fd; @@ -324,6 +326,7 @@ int drm_open_any_render(void) if (__sync_fetch_and_add(&open_count, 1)) return fd; + at_exit_drm_render_fd = dup(fd); gem_quiescent_gpu(fd); igt_install_exit_handler(quiescent_gpu_at_exit_render);