Mercurial > dovecot > core-2.2
changeset 9496:4fd624e60da1 HEAD
master: If time moves backwards, delay launching new processes.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 21 Jun 2009 21:46:46 -0400 |
parents | b9f5982e68ee |
children | 1769b18aea5b |
files | src/master/main.c src/master/service-monitor.c src/master/service-monitor.h src/master/service-process.c src/master/service.c src/master/service.h |
diffstat | 6 files changed, 77 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- 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 @@ 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; @@ -575,6 +595,8 @@ argc, argv); i_set_failure_prefix(""); + io_loop_set_time_moved_callback(current_ioloop, master_time_moved); + master_uid = geteuid(); master_gid = getegid();
--- 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) +#define SERVICE_STARTUP_FAILURE_THROTTLE_SECS 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); +void service_monitor_stop(struct service *service); static void service_status_input(struct service *service) { @@ -99,22 +97,13 @@ 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 @@ 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_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 @@ if (l->io != NULL) io_remove(&l->io); } + service->listening = FALSE; } void services_monitor_start(struct service_list *service_list) @@ -202,7 +193,7 @@ service_monitor_listen_stop(service_list->config); } -static void service_monitor_stop(struct service *service) +void service_monitor_stop(struct service *service) { int i;
--- 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 @@ /* 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
--- 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 @@ 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:
--- 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 @@ 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); + } +}
--- 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 @@ /* 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 @@ /* 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);