summaryrefslogtreecommitdiffstats
path: root/src/master/service.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 09:51:24 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 09:51:24 +0000
commitf7548d6d28c313cf80e6f3ef89aed16a19815df1 (patch)
treea3f6f2a3f247293bee59ecd28e8cd8ceb6ca064a /src/master/service.h
parentInitial commit. (diff)
downloaddovecot-f7548d6d28c313cf80e6f3ef89aed16a19815df1.tar.xz
dovecot-f7548d6d28c313cf80e6f3ef89aed16a19815df1.zip
Adding upstream version 1:2.3.19.1+dfsg1.upstream/1%2.3.19.1+dfsg1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--src/master/service.h209
1 files changed, 209 insertions, 0 deletions
diff --git a/src/master/service.h b/src/master/service.h
new file mode 100644
index 0000000..4412641
--- /dev/null
+++ b/src/master/service.h
@@ -0,0 +1,209 @@
+#ifndef SERVICE_H
+#define SERVICE_H
+
+#include "net.h"
+#include "master-settings.h"
+
+/* If a service process doesn't send its first status notification in
+ this many seconds, kill the process */
+#define SERVICE_FIRST_STATUS_TIMEOUT_SECS 30
+
+#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,
+ SERVICE_LISTENER_FIFO,
+ SERVICE_LISTENER_INET
+};
+
+struct service_listener {
+ struct service *service;
+
+ enum service_listener_type type;
+ int fd; /* may be -1 */
+ struct io *io;
+
+ const char *name;
+ const char *inet_address;
+
+ union {
+ struct {
+ const struct file_listener_settings *set;
+ uid_t uid;
+ gid_t gid;
+ } fileset;
+ struct {
+ const struct inet_listener_settings *set;
+ struct ip_addr ip;
+ } inetset;
+ } set;
+
+ bool reuse_port;
+};
+
+struct service {
+ struct service_list *list;
+
+ enum service_type type;
+
+ const struct service_settings *set;
+ const char *config_file_path;
+
+ const char *executable;
+ uid_t uid;
+ gid_t gid;
+ gid_t privileged_gid;
+ const char *extra_gids; /* comma-separated list */
+
+ /* all listeners, even those that aren't currently listening */
+ ARRAY(struct service_listener *) listeners;
+ /* linked list of all processes belonging to this service */
+ struct service_process *processes;
+
+ /* number of processes currently created for this service */
+ unsigned int process_count;
+ /* number of processes currently accepting new clients */
+ unsigned int process_avail;
+ /* max number of processes allowed */
+ unsigned int process_limit;
+ /* Total number of processes ever created */
+ uint64_t process_count_total;
+
+ /* Maximum number of client connections a process can handle. */
+ unsigned int client_limit;
+ /* Kill idling processes after this many seconds. */
+ unsigned int idle_kill;
+ /* set->vsz_limit or set->master_set->default_client_limit */
+ uoff_t vsz_limit;
+
+ /* log process pipe file descriptors. */
+ int log_fd[2];
+ /* fd that log process sees log_fd[0] as. can be used to identify
+ service name when sending commands via master_log_fd. */
+ int log_process_internal_fd;
+
+ /* status report pipe file descriptors */
+ int status_fd[2];
+ struct io *io_status;
+
+ int master_dead_pipe_fd[2];
+
+ unsigned int throttle_msecs;
+ time_t exit_failure_last;
+ unsigned int exit_failures_in_sec;
+
+ /* Login process's notify fd. We change its seek position to
+ communicate state to login processes. */
+ int login_notify_fd;
+ time_t last_login_notify_time;
+ struct timeout *to_login_notify;
+
+ /* if a process fails before servicing its first request, assume it's
+ broken and start throttling new process creations */
+ struct timeout *to_throttle;
+ /* 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;
+ unsigned int prefork_counter;
+
+ /* Last time a "dropping client connections" warning was logged */
+ time_t last_drop_warning;
+
+ /* all processes are in use and new connections are coming */
+ bool listen_pending:1;
+ /* service is currently listening for new connections */
+ bool listening:1;
+ /* TRUE if service has at least one inet_listener */
+ bool have_inet_listeners:1;
+ /* service_login_notify()'s last notification state */
+ bool last_login_full_notify:1;
+ /* service has exited at least once with exit code 0 */
+ bool have_successful_exits:1;
+ /* service was stopped via doveadm */
+ bool doveadm_stop:1;
+};
+
+struct service_list {
+ pool_t pool;
+ pool_t set_pool;
+ int refcount;
+ struct timeout *to_kill;
+ unsigned int fork_counter;
+
+ const struct master_settings *set;
+ const struct master_service_settings *service_set;
+
+ struct service *config;
+ struct service *log;
+ struct service *anvil;
+
+ struct file_listener_settings master_listener_set;
+ struct io *io_master;
+ int master_fd;
+
+ /* nonblocking log fds usd by master */
+ int master_log_fd[2];
+ struct service_process_notify *log_byes;
+
+ ARRAY(struct service *) services;
+
+ bool destroying:1;
+ bool destroyed:1;
+ bool sigterm_sent:1;
+ bool sigterm_sent_to_log:1;
+};
+
+HASH_TABLE_DEFINE_TYPE(pid_process, void *, struct service_process *);
+extern HASH_TABLE_TYPE(pid_process) service_pids;
+
+/* Create all services from settings */
+int services_create(const struct master_settings *set,
+ struct service_list **services_r, const char **error_r);
+
+/* Destroy services */
+void services_destroy(struct service_list *service_list, bool wait);
+
+void service_list_ref(struct service_list *service_list);
+void service_list_unref(struct service_list *service_list);
+
+/* Return path to configuration process socket. */
+const char *services_get_config_socket_path(struct service_list *service_list);
+
+/* Send a signal to all processes in a given service. However, if we're sending
+ a SIGTERM and a process hasn't yet sent the initial status notification,
+ that process is skipped. The number of such skipped processes are stored in
+ uninitialized_count_r. Returns the number of processes that a signal was
+ successfully sent to. */
+unsigned int service_signal(struct service *service, int signo,
+ unsigned int *uninitialized_count_r);
+/* Notify all processes (if necessary) that no more connections can be handled
+ by the service without killing existing connections (TRUE) or that they
+ can be (FALSE). */
+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 msecs);
+/* Time moved backwards. Throttle services that care about time. */
+void services_throttle_time_sensitives(struct service_list *list,
+ unsigned int msecs);
+
+/* Find service by name. */
+struct service *
+service_lookup(struct service_list *service_list, const char *name);
+/* Find service by type */
+struct service *
+service_lookup_type(struct service_list *service_list, enum service_type type);
+
+void service_error(struct service *service, const char *format, ...)
+ ATTR_FORMAT(2, 3);
+
+void service_pids_init(void);
+void service_pids_deinit(void);
+
+#endif