]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-master: When running under master, close listeners immediately on SIGQUIT
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 2 May 2017 13:13:08 +0000 (16:13 +0300)
committerGitLab <gitlab@git.dovecot.net>
Tue, 9 May 2017 13:58:21 +0000 (16:58 +0300)
src/lib-master/master-service.c

index 47dd88e8091248ba0dfd2c3e72f9bbbf13fb6753..fc30d21ffb565451f17fcf32828bf22026a77b5c 100644 (file)
@@ -86,6 +86,26 @@ static void sig_die(const siginfo_t *si, void *context)
        io_loop_stop(service->ioloop);
 }
 
+static void sig_close_listeners(const siginfo_t *si ATTR_UNUSED, void *context)
+{
+       struct master_service *service = context;
+
+       /* We're in a signal handler: Close listeners immediately so master
+          can successfully restart. We can safely close only those listeners
+          that don't have an io, but this shouldn't be a big problem. If there
+          is an active io, the service is unlikely to be unresposive for
+          longer periods of time, so the listener gets closed soon enough via
+          master_status_error(). */
+       for (unsigned int i = 0; i < service->socket_count; i++) {
+               if (service->listeners[i].fd != -1 &&
+                   service->listeners[i].io == NULL) {
+                       if (close(service->listeners[i].fd) < 0)
+                               lib_signals_syscall_error("signal: close(listener) failed: ");
+                       service->listeners[i].fd = -1;
+               }
+       }
+}
+
 static void
 sig_state_changed(const siginfo_t *si ATTR_UNUSED, void *context)
 {
@@ -522,6 +542,7 @@ void master_service_init_finish(struct master_service *service)
                /* start listening errors for status fd, it means master died */
                service->io_status_error = io_add(MASTER_DEAD_FD, IO_ERROR,
                                                  master_status_error, service);
+               lib_signals_set_handler(SIGQUIT, 0, sig_close_listeners, service);
        }
        master_service_io_listeners_add(service);
        if (service->want_ssl_settings &&