]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
master: Handle throttling of services in millisecond resolution internally.
authorStephan Bosch <stephan.bosch@dovecot.fi>
Sun, 16 Dec 2018 13:23:15 +0000 (14:23 +0100)
committerVille Savolainen <ville.savolainen@dovecot.fi>
Tue, 10 Sep 2019 07:01:48 +0000 (10:01 +0300)
src/master/main.c
src/master/master-client.c
src/master/service-monitor.c
src/master/service.c
src/master/service.h

index 477a9fb09fc350cf32fddd5f815a1296d163c31a..7aebb6873caf397f0759b057a8e8e760bb042a93 100644 (file)
@@ -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);
index 71880a763f2cc99717b9fe1ceca34477b3aa0c7f..73de3ae3a7c18252d178c23f9099d20a62a8cf09 100644 (file)
@@ -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,
index 748727f2c11989d610c5fdfa4006398fd024feab..b2408b56479c62e68ec6f36cb955b0bc143bd268 100644 (file)
@@ -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);
index 3fa25068ff8aa983b6ab9001145c02c382a1cd93..cc699eb268c2bbf90939d601c1f6af4af9bbfe7a 100644 (file)
@@ -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);
        }
 }
 
index 69902de9da6661b816b214d7f5a59e51c3813730..39f46abde46ea14ca44043115e1143c0efde38cb 100644 (file)
@@ -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 *