From: Stephan Bosch Date: Sun, 16 Dec 2018 13:23:15 +0000 (+0100) Subject: master: Handle throttling of services in millisecond resolution internally. X-Git-Tag: 2.3.8~202 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cc60ef0ec3e5bced7db9dd7578abbe3b9cb53b4b;p=thirdparty%2Fdovecot%2Fcore.git master: Handle throttling of services in millisecond resolution internally. --- diff --git a/src/master/main.c b/src/master/main.c index 477a9fb09f..7aebb6873c 100644 --- a/src/master/main.c +++ b/src/master/main.c @@ -10,6 +10,7 @@ #include "path-util.h" #include "ipwd.h" #include "str.h" +#include "time-util.h" #include "execv-const.h" #include "restrict-process-size.h" #include "master-instance.h" @@ -603,7 +604,7 @@ master_time_moved(const struct timeval *old_time, secs = old_time->tv_sec - new_time->tv_sec + 1; if (secs > SERVICE_TIME_MOVED_BACKWARDS_MAX_THROTTLE_SECS) secs = SERVICE_TIME_MOVED_BACKWARDS_MAX_THROTTLE_SECS; - services_throttle_time_sensitives(services, secs); + services_throttle_time_sensitives(services, secs * 1000); i_warning("Time moved backwards by %"PRIdTIME_T" seconds, waiting for " "%"PRIdTIME_T" secs until new services are launched again.", old_time - new_time, secs); diff --git a/src/master/master-client.c b/src/master/master-client.c index 71880a763f..73de3ae3a7 100644 --- a/src/master/master-client.c +++ b/src/master/master-client.c @@ -23,7 +23,8 @@ master_client_service_status_output(string_t *str, str_printfa(str, "\t%u\t%u\t%u\t%u\t%u\t%ld\t%u\t%ld\t%c\t%c\t%c\t%"PRIu64"\n", service->process_count, service->process_avail, service->process_limit, service->client_limit, - service->to_throttle == NULL ? 0 : service->throttle_secs, + (service->to_throttle == NULL ? + 0 : ((service->throttle_msecs + 999) / 1000)), (long)service->exit_failure_last, service->exit_failures_in_sec, (long)service->last_drop_warning, diff --git a/src/master/service-monitor.c b/src/master/service-monitor.c index 748727f2c1..b2408b5647 100644 --- a/src/master/service-monitor.c +++ b/src/master/service-monitor.c @@ -195,14 +195,19 @@ static void service_monitor_throttle(struct service *service) if (service->to_throttle != NULL || service->list->destroying) return; - i_assert(service->throttle_secs > 0); - - service_error(service, "command startup failed, throttling for %u secs", - service->throttle_secs); - service_throttle(service, service->throttle_secs); - service->throttle_secs *= 2; - if (service->throttle_secs > SERVICE_STARTUP_FAILURE_THROTTLE_MAX_SECS) - service->throttle_secs = SERVICE_STARTUP_FAILURE_THROTTLE_MAX_SECS; + i_assert(service->throttle_msecs > 0); + + service_error(service, + "command startup failed, throttling for %u.%03u secs", + service->throttle_msecs / 1000, + service->throttle_msecs % 1000); + service_throttle(service, service->throttle_msecs); + service->throttle_msecs *= 2; + if (service->throttle_msecs > + SERVICE_STARTUP_FAILURE_THROTTLE_MAX_MSECS) { + service->throttle_msecs = + SERVICE_STARTUP_FAILURE_THROTTLE_MAX_MSECS; + } } static void service_drop_timeout(struct service *service) @@ -706,8 +711,8 @@ void services_monitor_reap_children(void) /* success - one success resets all failures */ service->have_successful_exits = TRUE; service->exit_failures_in_sec = 0; - service->throttle_secs = - SERVICE_STARTUP_FAILURE_THROTTLE_MIN_SECS; + service->throttle_msecs = + SERVICE_STARTUP_FAILURE_THROTTLE_MIN_MSECS; throttle = FALSE; } else { throttle = service_process_failure(process, status); diff --git a/src/master/service.c b/src/master/service.c index 3fa25068ff..cc699eb268 100644 --- a/src/master/service.c +++ b/src/master/service.c @@ -210,7 +210,7 @@ service_create(pool_t pool, const struct service_settings *set, service = p_new(pool, struct service, 1); service->list = service_list; service->set = set; - service->throttle_secs = SERVICE_STARTUP_FAILURE_THROTTLE_MIN_SECS; + service->throttle_msecs = SERVICE_STARTUP_FAILURE_THROTTLE_MIN_MSECS; service->client_limit = set->client_limit != 0 ? set->client_limit : set->master_set->default_client_limit; @@ -712,7 +712,7 @@ static void service_drop_listener_connections(struct service *service) } } -void service_throttle(struct service *service, unsigned int secs) +void service_throttle(struct service *service, unsigned int msecs) { if (service->to_throttle != NULL || service->list->destroyed) return; @@ -721,12 +721,12 @@ void service_throttle(struct service *service, unsigned int secs) service_drop_listener_connections(service); service_monitor_listen_stop(service); - service->to_throttle = timeout_add(secs * 1000, - service_throttle_timeout, service); + service->to_throttle = timeout_add(msecs, service_throttle_timeout, + service); } void services_throttle_time_sensitives(struct service_list *list, - unsigned int secs) + unsigned int msecs) { struct service *const *services; @@ -734,7 +734,7 @@ void services_throttle_time_sensitives(struct service_list *list, struct service *service = *services; if (service->type == SERVICE_TYPE_UNKNOWN) - service_throttle(service, secs); + service_throttle(service, msecs); } } diff --git a/src/master/service.h b/src/master/service.h index 69902de9da..39f46abde4 100644 --- a/src/master/service.h +++ b/src/master/service.h @@ -8,8 +8,8 @@ this many seconds, kill the process */ #define SERVICE_FIRST_STATUS_TIMEOUT_SECS 30 -#define SERVICE_STARTUP_FAILURE_THROTTLE_MIN_SECS 2 -#define SERVICE_STARTUP_FAILURE_THROTTLE_MAX_SECS 60 +#define SERVICE_STARTUP_FAILURE_THROTTLE_MIN_MSECS (2*1000) +#define SERVICE_STARTUP_FAILURE_THROTTLE_MAX_MSECS (60*1000) enum service_listener_type { SERVICE_LISTENER_UNIX, @@ -89,7 +89,7 @@ struct service { int master_dead_pipe_fd[2]; - unsigned int throttle_secs; + unsigned int throttle_msecs; time_t exit_failure_last; unsigned int exit_failures_in_sec; @@ -186,10 +186,10 @@ unsigned int service_signal(struct service *service, int signo, void service_login_notify(struct service *service, bool all_processes_full); /* Prevent service from launching new processes for a while. */ -void service_throttle(struct service *service, unsigned int secs); +void service_throttle(struct service *service, unsigned int msecs); /* Time moved backwards. Throttle services that care about time. */ void services_throttle_time_sensitives(struct service_list *list, - unsigned int secs); + unsigned int msecs); /* Find service by name. */ struct service *