From 58aa56e033f8cbc3e94ae94e96a974e15e50ae28 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Mon, 21 Dec 2020 21:24:50 +0200 Subject: [PATCH] lib-master, master: Add "worker" service type 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 | 6 +++++- src/master/master-settings.c | 2 ++ src/master/service-monitor.c | 15 ++++++++++++++- src/master/service-process.c | 1 + src/master/service.h | 2 ++ 5 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/lib-master/service-settings.h b/src/lib-master/service-settings.h index da9986b533..c0235856ae 100644 --- a/src/lib-master/service-settings.h +++ b/src/lib-master/service-settings.h @@ -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, }; /* */ diff --git a/src/master/master-settings.c b/src/master/master-settings.c index ce07ebd654..80bce8bd4b 100644 --- a/src/master/master-settings.c +++ b/src/master/master-settings.c @@ -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); diff --git a/src/master/service-monitor.c b/src/master/service-monitor.c index 611caed14d..7ac76082e4 100644 --- a/src/master/service-monitor.c +++ b/src/master/service-monitor.c @@ -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) diff --git a/src/master/service-process.c b/src/master/service-process.c index b5c8f14f6e..2770c75503 100644 --- a/src/master/service-process.c +++ b/src/master/service-process.c @@ -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; diff --git a/src/master/service.h b/src/master/service.h index 39f46abde4..441264185e 100644 --- a/src/master/service.h +++ b/src/master/service.h @@ -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; -- 2.47.3