]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-master, master: Add "worker" service type
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Mon, 21 Dec 2020 19:24:50 +0000 (21:24 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Thu, 14 Jan 2021 11:16:54 +0000 (11:16 +0000)
The worker services are expected to reach their process_limit regularly.
There shouldn't be a warning logged about temporarily reaching the limit,
since it can happen due to race conditions.

src/lib-master/service-settings.h
src/master/master-settings.c
src/master/service-monitor.c
src/master/service-process.c
src/master/service.h

index da9986b5338a578da7c925a0ee905ad2e1511db9..c0235856ae39d1ea547c3f81c779adf9c9f01727 100644 (file)
@@ -16,7 +16,11 @@ enum service_type {
        SERVICE_TYPE_ANVIL,
        SERVICE_TYPE_CONFIG,
        SERVICE_TYPE_LOGIN,
-       SERVICE_TYPE_STARTUP
+       SERVICE_TYPE_STARTUP,
+       /* Worker processes are intentionally limited to their process_limit,
+          and they can regularly reach it. There shouldn't be unnecessary
+          warnings about temporarily reaching the limit. */
+       SERVICE_TYPE_WORKER,
 };
 /* </settings checks> */
 
index ce07ebd6549b4412e2d59215acdcb1405108fc89..80bce8bd4bb59ddf980b42bad47765d5f6150692 100644 (file)
@@ -346,6 +346,8 @@ static bool master_settings_parse_type(struct service_settings *set,
                set->parsed_type = SERVICE_TYPE_LOGIN;
        else if (strcmp(set->type, "startup") == 0)
                set->parsed_type = SERVICE_TYPE_STARTUP;
+       else if (strcmp(set->type, "worker") == 0)
+               set->parsed_type = SERVICE_TYPE_WORKER;
        else {
                *error_r = t_strconcat("Unknown service type: ",
                                       set->type, NULL);
index 611caed14d6652cd63ca041e5895f239c99d668a..7ac76082e4a3f628c8ac005f771744bd88e379cd 100644 (file)
@@ -23,6 +23,7 @@
 
 #define SERVICE_DROP_WARN_INTERVAL_SECS 1
 #define SERVICE_DROP_TIMEOUT_MSECS (10*1000)
+#define SERVICE_LOG_DROP_WARNING_DELAY_MSECS 500
 #define MAX_DIE_WAIT_MSECS 5000
 #define SERVICE_MAX_EXIT_FAILURES_IN_SEC 10
 #define SERVICE_PREFORK_MAX_AT_ONCE 10
@@ -92,6 +93,9 @@ static void service_status_less(struct service_process *process,
 {
        struct service *service = process->service;
 
+       /* some process got more connections - remove the delayed warning */
+       timeout_remove(&service->to_drop_warning);
+
        if (process->available_count == 0) {
                /* process can accept more clients again */
                if (service->process_avail++ == 0)
@@ -268,7 +272,8 @@ static void service_drop_connections(struct service_listener *l)
        struct service *service = l->service;
        int fd;
 
-       service_log_drop_warning(service);
+       if (service->type != SERVICE_TYPE_WORKER)
+               service_log_drop_warning(service);
 
        if (service->type == SERVICE_TYPE_LOGIN) {
                /* reached process limit, notify processes that they
@@ -281,6 +286,12 @@ static void service_drop_connections(struct service_listener *l)
                /* maybe this is a temporary peak, stop for a while and
                   see if it goes away */
                service_monitor_listen_pending(service);
+               if (service->to_drop_warning == NULL &&
+                   service->type == SERVICE_TYPE_WORKER) {
+                       service->to_drop_warning =
+                               timeout_add_short(SERVICE_LOG_DROP_WARNING_DELAY_MSECS,
+                                                 service_log_drop_warning, service);
+               }
        } else {
                /* this has been happening for a while now. just accept and
                   close the connection, so it's clear that this is happening
@@ -384,6 +395,7 @@ static void service_monitor_listen_start_force(struct service *service)
        service->listening = TRUE;
        service->listen_pending = FALSE;
        timeout_remove(&service->to_drop);
+       timeout_remove(&service->to_drop_warning);
 
        array_foreach(&service->listeners, listeners) {
                struct service_listener *l = *listeners;
@@ -415,6 +427,7 @@ void service_monitor_listen_stop(struct service *service)
        service->listening = FALSE;
        service->listen_pending = FALSE;
        timeout_remove(&service->to_drop);
+       timeout_remove(&service->to_drop_warning);
 }
 
 static int service_login_create_notify_fd(struct service *service)
index b5c8f14f6e7c3f4e48b1d3d83930eabf1521f58f..2770c75503483d49fc211e865872b98e896ac249 100644 (file)
@@ -126,6 +126,7 @@ service_dup_fds(struct service *service)
        case SERVICE_TYPE_UNKNOWN:
        case SERVICE_TYPE_LOGIN:
        case SERVICE_TYPE_STARTUP:
+       case SERVICE_TYPE_WORKER:
                dup2_append(&dups, service_anvil_global->blocking_fd[1],
                            MASTER_ANVIL_FD);
                break;
index 39f46abde46ea14ca44043115e1143c0efde38cb..441264185eef00f9407c57545563c9e63501a26b 100644 (file)
@@ -105,6 +105,8 @@ struct service {
        /* when process_limit is reached, wait for a while until we actually
           start dropping pending connections */
        struct timeout *to_drop;
+       /* delayed process_limit reached warning with SERVICE_TYPE_WORKER */
+       struct timeout *to_drop_warning;
 
        /* prefork processes up to process_min_avail if there's time */
        struct timeout *to_prefork;