]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-test: Add notification signal send/wait API
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Fri, 18 Jun 2021 11:19:36 +0000 (14:19 +0300)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Thu, 1 Jul 2021 07:22:34 +0000 (07:22 +0000)
This allows a simple way for child/parent processes to communicate when
they're ready. SIGHUP signal is reserved for this.

src/lib-test/test-subprocess.c
src/lib-test/test-subprocess.h

index 4c51924b7e85d4327b0c8a4476df18985b489876..aec1ddde5060ca7ac0668eb5e1a00b0838e83a47 100644 (file)
@@ -5,6 +5,7 @@
 #include "hostpid.h"
 #include "array.h"
 #include "ioloop.h"
+#include "sleep.h"
 #include "test-common.h"
 #include "test-subprocess.h"
 
@@ -18,6 +19,7 @@ struct test_subprocess {
 
 volatile sig_atomic_t test_subprocess_is_child = 0;
 static bool test_subprocess_lib_init = FALSE;
+static volatile bool test_subprocess_notification_signal_received = FALSE;
 static struct event *test_subprocess_event = NULL;
 static ARRAY(struct test_subprocess *) test_subprocesses = ARRAY_INIT;
 static void (*test_subprocess_cleanup_callback)(void) = NULL;
@@ -297,6 +299,41 @@ void test_subprocess_set_cleanup_callback(void (*callback)(void))
        test_subprocess_cleanup_callback = callback;
 }
 
+void test_subprocess_notify_signal_send(pid_t pid)
+{
+       if (kill(pid, SIGHUP) < 0)
+               i_fatal("kill(%ld, SIGHUP) failed: %m", (long)pid);
+}
+
+void test_subprocess_notify_signal_send_parent(void)
+{
+       test_subprocess_notify_signal_send(getppid());
+}
+
+void test_subprocess_notify_signal_reset(void)
+{
+       test_subprocess_notification_signal_received = FALSE;
+}
+
+void test_subprocess_notify_signal_wait(unsigned int timeout_msecs)
+{
+       unsigned int i, count = timeout_msecs / 10;
+
+       for (i = 0; i < count; i++) {
+               if (test_subprocess_notification_signal_received)
+                       return;
+               i_sleep_msecs(10);
+       }
+       i_fatal("Didn't receive wait notification signal from server");
+}
+
+static void
+test_subprocess_notification_signal(const siginfo_t *si ATTR_UNUSED,
+                                   void *context ATTR_UNUSED)
+{
+       test_subprocess_notification_signal_received = TRUE;
+}
+
 void test_subprocesses_init(bool debug)
 {
        if (!lib_is_initialized()) {
@@ -313,6 +350,8 @@ void test_subprocesses_init(bool debug)
        lib_signals_set_handler(SIGINT, 0, test_subprocess_terminate, NULL);
        lib_signals_set_handler(SIGSEGV, 0, test_subprocess_terminate, NULL);
        lib_signals_set_handler(SIGABRT, 0, test_subprocess_terminate, NULL);
+       lib_signals_set_handler(SIGHUP, LIBSIG_FLAG_RESTART,
+                               test_subprocess_notification_signal, NULL);
 
        i_array_init(&test_subprocesses, 8);
 
index fed6d0464f9b07bfddf5cbee1bd76f17c008df2f..35f630052635f2e7a1d99e3ff6fdd82b48945fab 100644 (file)
@@ -23,6 +23,18 @@ void test_subprocess_kill_all(unsigned int timeout_secs);
    exit()s unexpectedly. Note that this may be run in signal context. */
 void test_subprocess_set_cleanup_callback(void (*callback)(void));
 
+/* Send a notification signal (SIGHUP) to the given PID */
+void test_subprocess_notify_signal_send(pid_t pid);
+/* Send a notificatino signal to the parent process. */
+void test_subprocess_notify_signal_send_parent(void);
+/* Reset any previously sent notification signals. */
+void test_subprocess_notify_signal_reset(void);
+/* Wait until a notification signal is sent, or return immediately if it was
+   already sent. test_subprocess_notify_signal_reset() should be called before
+   this to make sure it's not returning due to a previously sent signal.
+   If the timeout is reached, i_fatal() is called. */
+void test_subprocess_notify_signal_wait(unsigned int timeout_msecs);
+
 void test_subprocesses_init(bool debug);
 void test_subprocesses_deinit(void);