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