From: Timo Sirainen Date: Tue, 2 May 2017 13:13:08 +0000 (+0300) Subject: lib-master: When running under master, close listeners immediately on SIGQUIT X-Git-Tag: 2.3.0.rc1~1649 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4cbe2b4ee234317331eadd1768d9ce433adb60e1;p=thirdparty%2Fdovecot%2Fcore.git lib-master: When running under master, close listeners immediately on SIGQUIT --- diff --git a/src/lib-master/master-service.c b/src/lib-master/master-service.c index 47dd88e809..fc30d21ffb 100644 --- a/src/lib-master/master-service.c +++ b/src/lib-master/master-service.c @@ -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 &&