]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-smtp: test-smtp-server-errors: Make detection of early termination of child proce...
authorStephan Bosch <stephan.bosch@dovecot.fi>
Sun, 8 Apr 2018 13:20:22 +0000 (15:20 +0200)
committerVille Savolainen <ville.savolainen@dovecot.fi>
Fri, 27 Apr 2018 10:40:00 +0000 (13:40 +0300)
src/lib-smtp/test-smtp-server-errors.c

index d1bddbcd9f6a4b5999ac0b0c667d3a2ab56c5fa8..65fd399b7722dbd31e972a4b057ad8d73613e37c 100644 (file)
@@ -48,6 +48,7 @@ static struct ip_addr bind_ip;
 static in_port_t bind_port = 0;
 static struct ioloop *ioloop;
 static bool debug = FALSE;
+static volatile bool killing_children = FALSE;
 
 /* server */
 static struct smtp_server *smtp_server = NULL;
@@ -1478,20 +1479,32 @@ static int test_open_server_fd(void)
        return fd;
 }
 
+static void test_clients_kill_one(unsigned int index, pid_t pid)
+{
+       (void)kill(pid, SIGKILL);
+       if (waitpid(pid, NULL, 0) < 0 &&
+           errno == ECHILD) {
+               test_out_quiet(
+                       t_strdup_printf("client [%u] (pid=%u) still running",
+                                       index, (unsigned int)pid), FALSE);
+       }
+}
+
 static void test_clients_kill_all(void)
 {
        unsigned int i;
 
+       killing_children = TRUE;
        if (client_pids_count > 0) {
                for (i = 0; i < client_pids_count; i++) {
                        if (client_pids[i] != (pid_t)-1) {
-                               (void)kill(client_pids[i], SIGKILL);
-                               (void)waitpid(client_pids[i], NULL, 0);
+                               test_clients_kill_one(i+1, client_pids[i]);
                                client_pids[i] = -1;
                        }
                }
        }
        client_pids_count = 0;
+       killing_children = FALSE;
 }
 
 static void test_run_client_server(
@@ -1532,10 +1545,14 @@ static void test_run_client_server(
                                client_test(i);
                                io_loop_destroy(&ioloop);
                                i_free(client_pids);
+
+                               if (debug)
+                                       i_debug("Waiting to be killed");
                                /* wait for it to be killed; this way, valgrind
                                   will not object to this process going away
                                   inelegantly. */
                                sleep(60);
+
                                exit(1);
                        }
                }
@@ -1577,6 +1594,22 @@ test_signal_handler(int signo)
        raise(signo);
 }
 
+static void
+test_child_handler(int signo ATTR_UNUSED)
+{
+       int saved_errno = errno;
+
+       if (killing_children) {
+               /* waitpid() is used in test_clients_kill_all() to check
+                  whether child was still running. Therefore, we must not
+                  wait for it here when that is happening. */
+               return;
+       }
+
+       while (waitpid((pid_t)(-1), 0, WNOHANG) > 0) {}
+       errno = saved_errno;
+}
+
 static void test_atexit(void)
 {
        test_clients_kill_all();
@@ -1587,12 +1620,12 @@ int main(int argc, char *argv[])
        int c;
 
        atexit(test_atexit);
-       (void)signal(SIGCHLD, SIG_IGN);
        (void)signal(SIGTERM, test_signal_handler);
        (void)signal(SIGQUIT, test_signal_handler);
        (void)signal(SIGINT, test_signal_handler);
        (void)signal(SIGSEGV, test_signal_handler);
        (void)signal(SIGABRT, test_signal_handler);
+       (void)signal(SIGCHLD, test_child_handler);
 
        while ((c = getopt(argc, argv, "D")) > 0) {
                switch (c) {