]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
master, log: Pass config fd from master to log process
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Fri, 9 Dec 2022 22:13:26 +0000 (00:13 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Fri, 27 Jan 2023 13:01:47 +0000 (13:01 +0000)
The log process must not depend on the config process, because they would
have a circular dependency. Previously the configuration was sent to the
log process via environment filled by the master process. Now that we have
the full config available in a file descriptor, pass that config fd instead.

src/lib-master/master-interface.h
src/master/common.h
src/master/main.c
src/master/service-process.c

index 9966bec4056b1871dfde032ba4113e7ffb34cff9..0c3ab6909da7c3dc2ed05ddd1c232a6233f50111 100644 (file)
@@ -102,13 +102,15 @@ enum master_login_state {
 /* Pipe to master, used to detect when it dies. (MASTER_STATUS_FD would have
    been fine for this, except it's inefficient in Linux) */
 #define MASTER_DEAD_FD 6
+/* Configuration file descriptor. */
+#define MASTER_CONFIG_FD 7
 /* First file descriptor where process is expected to be listening.
    The file descriptor count is given in -s parameter, defaulting to 1.
 
    master_status.available_count reports how many accept()s we're still
    accepting. Once no children are listening, master will do it and create
    new child processes when needed. */
-#define MASTER_LISTEN_FD_FIRST 7
+#define MASTER_LISTEN_FD_FIRST 8
 
 /* Timeouts: base everything on how long we can wait for login clients. */
 #define MASTER_LOGIN_TIMEOUT_SECS (3*60)
index f88a496910e34f373fb2b6a6437103535f073fb5..5f644e14d1c83378687073983ed1bfa27db536a0 100644 (file)
@@ -16,6 +16,7 @@ extern bool have_proc_sys_kernel_core_pattern;
 extern const char *ssl_manual_key_password;
 extern int global_master_dead_pipe_fd[2];
 extern struct log_error_buffer *log_error_buffer;
+extern int global_config_fd;
 extern struct service_list *services;
 extern bool startup_finished;
 
index afc0b000faac9157b64ce19182514988d7796835..37f1f9eb3f6f59d9cf2388e416b80a73324e2b55 100644 (file)
@@ -62,6 +62,7 @@ bool have_proc_sys_kernel_core_pattern;
 const char *ssl_manual_key_password;
 int global_master_dead_pipe_fd[2];
 struct log_error_buffer *log_error_buffer;
+int global_config_fd = -1;
 struct service_list *services;
 bool startup_finished = FALSE;
 
@@ -420,12 +421,16 @@ sig_settings_reload(const siginfo_t *si ATTR_UNUSED,
        input.config_path = services_get_config_socket_path(services);
        input.never_exec = TRUE;
        input.reload_config = TRUE;
+       input.return_config_fd = TRUE;
        if (master_service_settings_read(master_service, &input,
                                         &output, &error) < 0) {
                i_error("Error reading configuration: %s", error);
                i_sd_notify(0, "READY=1");
                return;
        }
+       i_close_fd(&global_config_fd);
+       global_config_fd = output.config_fd;
+       fd_close_on_exec(global_config_fd, TRUE);
        set = master_service_settings_get_root_set(master_service,
                                                   &master_setting_parser_info);
 
@@ -500,9 +505,12 @@ static struct master_settings *master_settings_read(void)
        input.roots = set_roots;
        input.preserve_environment = TRUE;
        input.always_exec = TRUE;
+       input.return_config_fd = TRUE;
        if (master_service_settings_read(master_service, &input, &output,
                                         &error) < 0)
                i_fatal("Error reading configuration: %s", error);
+       global_config_fd = output.config_fd;
+       fd_close_on_exec(global_config_fd, TRUE);
        return master_service_settings_get_root_set(master_service,
                                                    &master_setting_parser_info);
 }
index be42627ae356c0696b7effcbba95ac872c876920..206ae65fa2bda42c517d761146bdb8e6c41c6acd 100644 (file)
@@ -218,6 +218,18 @@ service_dup_fds(struct service *service)
                i_set_failure_internal();
        }
 
+       if (service->type == SERVICE_TYPE_LOG) {
+               /* Pass our config fd to the log process, so it won't depend
+                  on config process. Note that we don't want to do this for
+                  other processes, since it prevents config reload. */
+               i_assert(global_config_fd != -1);
+               fd_close_on_exec(global_config_fd, FALSE);
+               if (lseek(global_config_fd, 0, SEEK_SET) < 0)
+                       i_fatal("lseek(config fd, 0) failed: %m");
+               dup2_append(&dups, global_config_fd, MASTER_CONFIG_FD);
+               env_put(DOVECOT_CONFIG_FD_ENV, dec2str(MASTER_CONFIG_FD));
+       }
+
        /* Switch log writing back to stderr before the log fds are closed.
           There's no guarantee that writing to stderr is visible anywhere, but
           it's better than the process just dying with FATAL_LOGWRITE. */
@@ -270,26 +282,10 @@ drop_privileges(struct service *service)
 
 static void service_process_setup_config_environment(struct service *service)
 {
-       const struct master_service_settings *set = service->list->service_set;
-
        switch (service->type) {
        case SERVICE_TYPE_CONFIG:
                env_put(MASTER_CONFIG_FILE_ENV, service->config_file_path);
                break;
-       case SERVICE_TYPE_LOG:
-               /* give the log's configuration directly, so it won't depend
-                  on config process */
-               env_put("DOVECONF_ENV", "1");
-               env_put("LOG_PATH", set->log_path);
-               env_put("INFO_LOG_PATH", set->info_log_path);
-               env_put("DEBUG_LOG_PATH", set->debug_log_path);
-               env_put("LOG_TIMESTAMP", set->log_timestamp);
-               env_put("SYSLOG_FACILITY", set->syslog_facility);
-               env_put("INSTANCE_NAME", set->instance_name);
-               if (set->verbose_proctitle)
-                       env_put("VERBOSE_PROCTITLE", "1");
-               env_put("SSL", "no");
-               break;
        default:
                env_put(MASTER_CONFIG_FILE_ENV,
                        services_get_config_socket_path(service->list));