From: Pierre Le Marre Date: Mon, 18 Sep 2023 11:17:31 +0000 (+0200) Subject: Test: Catch SIGUSR1 from Xvfb for X11 tests X-Git-Tag: accepted/tizen/unified/20240109.155348~82 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fupstream%2Flibxkbcommon.git;a=commitdiff_plain;h=266427723a649f02348e252ef82079d0f45792cc 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. --- 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. */