dovecot-2.1: master: Wait for services to stop listening before ...
dovecot at dovecot.org
dovecot at dovecot.org
Sat Nov 5 19:07:39 EET 2011
details: http://hg.dovecot.org/dovecot-2.1/rev/6894298ae5fd
changeset: 13662:6894298ae5fd
user: Timo Sirainen <tss at iki.fi>
date: Sat Nov 05 19:17:59 2011 +0200
description:
master: Wait for services to stop listening before unlinking the pid file.
diffstat:
src/master/main.c | 19 ++++++++++++++++---
src/master/service-monitor.c | 41 +++++++++++++++++++++++++++++++++++++----
src/master/service-monitor.h | 2 +-
src/master/service.c | 7 ++++---
src/master/service.h | 3 ++-
5 files changed, 60 insertions(+), 12 deletions(-)
diffs (188 lines):
diff -r 21145b853d64 -r 6894298ae5fd src/master/main.c
--- a/src/master/main.c Sat Nov 05 17:59:11 2011 +0200
+++ b/src/master/main.c Sat Nov 05 19:17:59 2011 +0200
@@ -330,7 +330,7 @@
services->config->config_file_path);
/* switch to new configuration. */
- services_monitor_stop(services);
+ services_monitor_stop(services, FALSE);
if (services_listen_using(new_services, services) < 0) {
services_monitor_start(services);
return;
@@ -342,7 +342,7 @@
while (service->processes != NULL)
service_process_destroy(service->processes);
}
- services_destroy(services);
+ services_destroy(services, FALSE);
services = new_services;
services_monitor_start(services);
@@ -455,13 +455,26 @@
services_monitor_start(services);
}
+static void global_dead_pipe_close(void)
+{
+ if (close(global_master_dead_pipe_fd[0]) < 0)
+ i_error("close(global dead pipe) failed: %m");
+ if (close(global_master_dead_pipe_fd[1]) < 0)
+ i_error("close(global dead pipe) failed: %m");
+ global_master_dead_pipe_fd[0] = -1;
+ global_master_dead_pipe_fd[1] = -1;
+}
+
static void main_deinit(void)
{
+ /* kill services and wait for them to die before unlinking pid file */
+ global_dead_pipe_close();
+ services_destroy(services, TRUE);
+
if (unlink(pidfile_path) < 0)
i_error("unlink(%s) failed: %m", pidfile_path);
i_free(pidfile_path);
- services_destroy(services);
service_anvil_global_deinit();
service_pids_deinit();
}
diff -r 21145b853d64 -r 6894298ae5fd src/master/service-monitor.c
--- a/src/master/service-monitor.c Sat Nov 05 17:59:11 2011 +0200
+++ b/src/master/service-monitor.c Sat Nov 05 19:17:59 2011 +0200
@@ -23,6 +23,7 @@
#define SERVICE_STARTUP_FAILURE_THROTTLE_SECS 60
#define SERVICE_DROP_WARN_INTERVAL_SECS 60
#define SERVICE_DROP_TIMEOUT_MSECS (10*1000)
+#define MAX_DIE_WAIT_SECS 5
static void service_monitor_start_extra_avail(struct service *service);
static void service_status_more(struct service_process *process,
@@ -171,8 +172,10 @@
if (ret <= 0) {
if (ret == 0)
service_error(service, "read(status) failed: EOF");
+ else if (errno != EAGAIN)
+ service_error(service, "read(status) failed: %m");
else
- service_error(service, "read(status) failed: %m");
+ return;
service_monitor_stop(service);
return;
}
@@ -467,7 +470,28 @@
timeout_remove(&service->to_throttle);
}
-void services_monitor_stop(struct service_list *service_list)
+static void services_monitor_wait(struct service_list *service_list)
+{
+ struct service *const *servicep;
+ time_t max_wait_time = time(NULL) + MAX_DIE_WAIT_SECS;
+ bool finished;
+
+ for (;;) {
+ finished = TRUE;
+ services_monitor_reap_children();
+ array_foreach(&service_list->services, servicep) {
+ if ((*servicep)->status_fd[0] != -1)
+ service_status_input(*servicep);
+ if ((*servicep)->process_avail > 0)
+ finished = FALSE;
+ }
+ if (finished || time(NULL) > max_wait_time)
+ break;
+ usleep(100000);
+ }
+}
+
+void services_monitor_stop(struct service_list *service_list, bool wait)
{
struct service *const *services;
@@ -480,6 +504,13 @@
service_list->master_dead_pipe_fd[1] = -1;
}
+ if (wait) {
+ /* we've notified all children that the master is dead.
+ now wait for the children to either die or to tell that
+ they're no longer listening for new connections */
+ services_monitor_wait(service_list);
+ }
+
array_foreach(&service_list->services, services)
service_monitor_stop(*services);
@@ -516,7 +547,8 @@
service = process->service;
if (status == 0) {
/* success */
- if (service->listen_pending)
+ if (service->listen_pending &&
+ !service->list->destroying)
service_monitor_listen_start(service);
throttle = FALSE;
} else {
@@ -535,7 +567,8 @@
service_monitor_throttle(service);
service_stopped = service->status_fd[0] == -1;
if (!service_stopped) {
- service_monitor_start_extra_avail(service);
+ if (!service->list->destroying)
+ service_monitor_start_extra_avail(service);
if (service->to_throttle == NULL)
service_monitor_listen_start(service);
}
diff -r 21145b853d64 -r 6894298ae5fd src/master/service-monitor.h
--- a/src/master/service-monitor.h Sat Nov 05 17:59:11 2011 +0200
+++ b/src/master/service-monitor.h Sat Nov 05 19:17:59 2011 +0200
@@ -5,7 +5,7 @@
void services_monitor_start(struct service_list *service_list);
/* Stop services. */
-void services_monitor_stop(struct service_list *service_list);
+void services_monitor_stop(struct service_list *service_list, bool wait);
/* Call after SIGCHLD has been detected */
void services_monitor_reap_children(void);
diff -r 21145b853d64 -r 6894298ae5fd src/master/service.c
--- a/src/master/service.c Sat Nov 05 17:59:11 2011 +0200
+++ b/src/master/service.c Sat Nov 05 19:17:59 2011 +0200
@@ -615,12 +615,13 @@
}
}
-void services_destroy(struct service_list *service_list)
+void services_destroy(struct service_list *service_list, bool wait)
{
/* make sure we log if child processes died unexpectedly */
- services_monitor_reap_children();
+ service_list->destroying = TRUE;
+ services_monitor_reap_children();
- services_monitor_stop(service_list);
+ services_monitor_stop(service_list, wait);
if (service_list->refcount > 1 &&
service_list->service_set->shutdown_clients) {
diff -r 21145b853d64 -r 6894298ae5fd src/master/service.h
--- a/src/master/service.h Sat Nov 05 17:59:11 2011 +0200
+++ b/src/master/service.h Sat Nov 05 19:17:59 2011 +0200
@@ -126,6 +126,7 @@
ARRAY_DEFINE(services, struct service *);
+ unsigned int destroying:1;
unsigned int destroyed:1;
unsigned int sigterm_sent:1;
unsigned int sigterm_sent_to_log:1;
@@ -138,7 +139,7 @@
struct service_list **services_r, const char **error_r);
/* Destroy services */
-void services_destroy(struct service_list *service_list);
+void services_destroy(struct service_list *service_list, bool wait);
void service_list_ref(struct service_list *service_list);
void service_list_unref(struct service_list *service_list);
More information about the dovecot-cvs
mailing list