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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
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. */