dovecot-2.0: master: If time moves backwards, delay launching ne...

dovecot at dovecot.org dovecot at dovecot.org
Mon Jun 22 04:38:19 EEST 2009


details:   http://hg.dovecot.org/dovecot-2.0/rev/4fd624e60da1
changeset: 9496:4fd624e60da1
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Jun 21 21:46:46 2009 -0400
description:
master: If time moves backwards, delay launching new processes.

diffstat:

6 files changed, 78 insertions(+), 18 deletions(-)
src/master/main.c            |   22 ++++++++++++++++++++++
src/master/service-monitor.c |   27 +++++++++------------------
src/master/service-monitor.h |    4 ++++
src/master/service-process.c |    5 +++++
src/master/service.c         |   30 ++++++++++++++++++++++++++++++
src/master/service.h         |    8 ++++++++

diffs (231 lines):

diff -r b9f5982e68ee -r 4fd624e60da1 src/master/main.c
--- a/src/master/main.c	Sun Jun 21 21:45:52 2009 -0400
+++ b/src/master/main.c	Sun Jun 21 21:46:46 2009 -0400
@@ -1,6 +1,7 @@
 /* Copyright (c) 2005-2009 Dovecot authors, see the included COPYING file */
 
 #include "common.h"
+#include "ioloop.h"
 #include "lib-signals.h"
 #include "fd-close-on-exec.h"
 #include "array.h"
@@ -28,6 +29,7 @@
 
 #define FATAL_FILENAME "master-fatal.lastlog"
 #define MASTER_PID_FILE_NAME "master.pid"
+#define SERVICE_TIME_MOVED_BACKWARDS_MAX_THROTTLE_SECS (60*3)
 
 struct master_service *master_service;
 uid_t master_uid;
@@ -418,6 +420,24 @@ static const char *get_full_config_path(
 	return p_strconcat(list->pool, cwd, "/", path, NULL);
 }
 
+static void master_time_moved(time_t old_time, time_t new_time)
+{
+	unsigned long secs;
+
+	if (new_time >= old_time)
+		return;
+
+	/* time moved backwards. disable launching new service processes
+	   until  */
+	secs = old_time - new_time + 1;
+	if (secs > SERVICE_TIME_MOVED_BACKWARDS_MAX_THROTTLE_SECS)
+		secs = SERVICE_TIME_MOVED_BACKWARDS_MAX_THROTTLE_SECS;
+	services_throttle_time_sensitives(services, secs);
+	i_warning("Time moved backwards by %lu seconds, "
+		  "waiting for %lu secs until new services are launched again.",
+		  (unsigned long)(old_time - new_time), secs);
+}
+
 static void daemonize(void)
 {
 	pid_t pid;
@@ -574,6 +594,8 @@ int main(int argc, char *argv[])
 				MASTER_SERVICE_FLAG_DONT_LOG_TO_STDERR,
 				argc, argv);
 	i_set_failure_prefix("");
+
+	io_loop_set_time_moved_callback(current_ioloop, master_time_moved);
 
 	master_uid = geteuid();
 	master_gid = getegid();
diff -r b9f5982e68ee -r 4fd624e60da1 src/master/service-monitor.c
--- a/src/master/service-monitor.c	Sun Jun 21 21:45:52 2009 -0400
+++ b/src/master/service-monitor.c	Sun Jun 21 21:46:46 2009 -0400
@@ -15,11 +15,9 @@
 #include <sys/wait.h>
 #include <syslog.h>
 
-#define THROTTLE_TIMEOUT (1000*60)
-
-static void service_monitor_stop(struct service *service);
-static void service_monitor_listen_start(struct service *service);
-static void service_monitor_listen_stop(struct service *service);
+#define SERVICE_STARTUP_FAILURE_THROTTLE_SECS 60
+
+void service_monitor_stop(struct service *service);
 
 static void service_status_input(struct service *service)
 {
@@ -99,22 +97,13 @@ static void service_status_input(struct 
 	process->available_count = status.available_count;
 }
 
-static void service_throttle_timeout(struct service *service)
-{
-	timeout_remove(&service->to_throttle);
-	service_monitor_listen_start(service);
-}
-
 static void service_monitor_throttle(struct service *service)
 {
 	if (service->to_throttle != NULL)
 		return;
 
 	service_error(service, "command startup failed, throttling");
-	service_monitor_listen_stop(service);
-
-	service->to_throttle = timeout_add(THROTTLE_TIMEOUT,
-					   service_throttle_timeout, service);
+	service_throttle(service, SERVICE_STARTUP_FAILURE_THROTTLE_SECS);
 }
 
 static void service_accept(struct service *service)
@@ -136,11 +125,12 @@ static void service_accept(struct servic
 		service_monitor_listen_stop(service);
 }
 
-static void service_monitor_listen_start(struct service *service)
+void service_monitor_listen_start(struct service *service)
 {
 	struct service_listener *const *listeners;
 	unsigned int i, count;
 
+	service->listening = TRUE;
 	service->listen_pending = FALSE;
 
 	listeners = array_get(&service->listeners, &count);
@@ -152,7 +142,7 @@ static void service_monitor_listen_start
 	}
 }
 
-static void service_monitor_listen_stop(struct service *service)
+void service_monitor_listen_stop(struct service *service)
 {
 	struct service_listener *const *listeners;
 	unsigned int i, count;
@@ -164,6 +154,7 @@ static void service_monitor_listen_stop(
 		if (l->io != NULL)
 			io_remove(&l->io);
 	}
+	service->listening = FALSE;
 }
 
 void services_monitor_start(struct service_list *service_list)
@@ -202,7 +193,7 @@ void services_monitor_start(struct servi
 		service_monitor_listen_stop(service_list->config);
 }
 
-static void service_monitor_stop(struct service *service)
+void service_monitor_stop(struct service *service)
 {
 	int i;
 
diff -r b9f5982e68ee -r 4fd624e60da1 src/master/service-monitor.h
--- a/src/master/service-monitor.h	Sun Jun 21 21:45:52 2009 -0400
+++ b/src/master/service-monitor.h	Sun Jun 21 21:46:46 2009 -0400
@@ -10,4 +10,8 @@ void services_monitor_stop(struct servic
 /* Call after SIGCHLD has been detected */
 void services_monitor_reap_children(struct service_list *service_list);
 
+void service_monitor_stop(struct service *service);
+void service_monitor_listen_start(struct service *service);
+void service_monitor_listen_stop(struct service *service);
+
 #endif
diff -r b9f5982e68ee -r 4fd624e60da1 src/master/service-process.c
--- a/src/master/service-process.c	Sun Jun 21 21:45:52 2009 -0400
+++ b/src/master/service-process.c	Sun Jun 21 21:46:46 2009 -0400
@@ -383,6 +383,11 @@ service_process_create(struct service *s
 	int fd[2];
 	pid_t pid;
 
+	if (!service->listening) {
+		/* probably throttling service, don't create new processes */
+		return NULL;
+	}
+
 	switch (service->type) {
 	case SERVICE_TYPE_AUTH_SOURCE:
 	case SERVICE_TYPE_AUTH_SERVER:
diff -r b9f5982e68ee -r 4fd624e60da1 src/master/service.c
--- a/src/master/service.c	Sun Jun 21 21:45:52 2009 -0400
+++ b/src/master/service.c	Sun Jun 21 21:46:46 2009 -0400
@@ -1,6 +1,7 @@
 /* Copyright (c) 2005-2009 Dovecot authors, see the included COPYING file */
 
 #include "common.h"
+#include "ioloop.h"
 #include "array.h"
 #include "aqueue.h"
 #include "hash.h"
@@ -421,3 +422,32 @@ void services_destroy(struct service_lis
 	hash_table_destroy(&service_list->pids);
 	pool_unref(&service_list->pool);
 }
+
+static void service_throttle_timeout(struct service *service)
+{
+	timeout_remove(&service->to_throttle);
+	service_monitor_listen_start(service);
+}
+
+void service_throttle(struct service *service, unsigned int secs)
+{
+	if (service->to_throttle != NULL)
+		return;
+
+	service_monitor_listen_stop(service);
+	service->to_throttle = timeout_add(secs * 1000,
+					   service_throttle_timeout, service);
+}
+
+void services_throttle_time_sensitives(struct service_list *list,
+				       unsigned int secs)
+{
+	struct service *const *services;
+	unsigned int i, count;
+
+	services = array_get(&list->services, &count);
+	for (i = 0; i < count; i++) {
+		if (services[i]->type == SERVICE_TYPE_UNKNOWN)
+			service_throttle(services[i], secs);
+	}
+}
diff -r b9f5982e68ee -r 4fd624e60da1 src/master/service.h
--- a/src/master/service.h	Sun Jun 21 21:45:52 2009 -0400
+++ b/src/master/service.h	Sun Jun 21 21:46:46 2009 -0400
@@ -88,6 +88,8 @@ struct service {
 
 	/* all processes are in use and new connections are coming */
 	unsigned int listen_pending:1;
+	/* service is currently listening for new connections */
+	unsigned int listening:1;
 };
 
 struct service_list {
@@ -122,6 +124,12 @@ void services_destroy(struct service_lis
 /* Send a signal to all processes in a given service */
 void service_signal(struct service *service, int signo);
 
+/* Prevent service from launching new processes for a while. */
+void service_throttle(struct service *service, unsigned int secs);
+/* Time moved backwards. Throttle services that care about time. */
+void services_throttle_time_sensitives(struct service_list *list,
+				       unsigned int secs);
+
 void service_error(struct service *service, const char *format, ...)
 	ATTR_FORMAT(2, 3);
 


More information about the dovecot-cvs mailing list