From 266427723a649f02348e252ef82079d0f45792cc Mon Sep 17 00:00:00 2001 From: Pierre Le Marre Date: Mon, 18 Sep 2023 13:17:31 +0200 Subject: [PATCH] Test: Catch SIGUSR1 from Xvfb for X11 tests Based on the work done by Peter Hutterer. Original commit message: If SIGUSR1 is set to SIG_IGN, X servers (all of them, including Xvfb) will send that signal to the parent process when they're ready to accept connections. We can use that instead of a hardcoded sleep which brings the wait down to ~37ms on my box. --- test/xvfb-wrapper.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/test/xvfb-wrapper.c b/test/xvfb-wrapper.c index d9fa0a7..38d159b 100644 --- a/test/xvfb-wrapper.c +++ b/test/xvfb-wrapper.c @@ -35,17 +35,28 @@ #include "xvfb-wrapper.h" #include "xkbcommon/xkbcommon-x11.h" +static bool xvfb_is_ready; + +static void +sigusr1_handler(int signal) +{ + xvfb_is_ready = true; +} + int xvfb_wrapper(int (*test_func)(char* display)) { int ret = 0; FILE * display_fd; char display_fd_string[32]; + sigset_t mask; + struct sigaction sa; char *xvfb_argv[] = { (char *) "Xvfb", (char *) "-displayfd", display_fd_string, NULL }; char *envp[] = { NULL }; pid_t xvfb_pid = 0; + size_t counter = 0; char display[32] = ":"; size_t length; @@ -57,6 +68,18 @@ xvfb_wrapper(int (*test_func)(char* display)) } snprintf(display_fd_string, sizeof(display_fd_string), "%d", fileno(display_fd)); + /* Set SIGUSR1 to SIG_IGN so Xvfb will send us that signal + * when it's ready to accept connections */ + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + sigprocmask(SIG_BLOCK, &mask, NULL); + sa.sa_handler = SIG_IGN; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sigaction(SIGUSR1, &sa, NULL); + + xvfb_is_ready = false; + /* * Xvfb command: let the server find an available display. * @@ -71,8 +94,21 @@ xvfb_wrapper(int (*test_func)(char* display)) goto err_xvfd; } - /* Wait for Xvfb fully waking up to accept a connection from a client. */ - sleep(1); + sa.sa_handler = SIG_DFL; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sigaction(SIGUSR1, &sa, NULL); + signal(SIGUSR1, sigusr1_handler); + sigprocmask (SIG_UNBLOCK, &mask, NULL); + + /* Now wait for the SIGUSR1 signal that Xvfb is ready */ + while (!xvfb_is_ready) { + usleep(1000); + if (++counter >= 3000) /* 3 seconds max wait */ + break; + } + + signal(SIGUSR1, SIG_DFL); /* Retrieve the display number: Xvfd writes the display number as a newline- * terminated string; copy this number to form a proper display string. */ -- 2.7.4