From: Valentine Krasnobaeva Date: Fri, 9 Aug 2024 16:29:14 +0000 (+0200) Subject: MEDIUM: startup: introduce load_cfg and read_cfg X-Git-Tag: v3.1-dev10~38 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0ed262d7bf2b628d620886175605e74d94ec1aa2;p=thirdparty%2Fhaproxy.git MEDIUM: startup: introduce load_cfg and read_cfg This commit is a part of the series to add a support of discovery mode in the configuration parser and in initialization sequence. In order to support discovery mode, we need to read the configuration twice. So, we need to split the stage, when we load all configuration files, from the stage when we parse it. To do this, let's encapsulate in read_cfg() the part, where we load the configuration files in a separate function, load_cfg(). Like this we can call only the parsing part as many times as we need. Before reading configuration at the first time we set MODE_DISCOVERY. After the reading this mode is immediately unset, as the real runtime mode has been already set by discovery keywords parsers. Second read is performed when all primary runtime modes (daemon, master-worker) are applied, because we should not read the configuration twice in the master process. --- diff --git a/src/haproxy.c b/src/haproxy.c index 0115808007..0ecf42a21d 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -1160,18 +1160,15 @@ next_dir_entry: free(err); } -/* Reads config files. Returns -1, if we are run out of memory, - * couldn't open provided file(s) or parser has detected some fatal error. - * Otherwise, returns an err_code, which may contain 0 (OK) or ERR_WARN, - * ERR_ALERT. It is used in further initialization stages. Process initial - * environment is preserved in the init_env ptr array, as some keywords and - * conditional blocks (.if/.else) could modify it. +/* Loads config files. Returns -1 and frees allocated memory in env_cfgfiles, if + * we are run out of memory or load_cfg_in_mem() has failed. load_cfg_in_mem() + * frees in its stack the memory allocated for config files content, if it has + * encountered an error. */ -static int read_cfg(char *progname) +static int load_cfg(char *progname) { - char *env_cfgfiles = NULL; struct cfgfile *cfg, *cfg_tmp; - int err_code = 0; + char *env_cfgfiles = NULL; /* handle cfgfiles that are actually directories */ cfgfiles_expand_directories(); @@ -1179,24 +1176,7 @@ static int read_cfg(char *progname) if (LIST_ISEMPTY(&cfg_cfgfiles)) usage(progname); - /* backup initial process env, because parse_cfg() could modify it with - * setenv/unsetenv/presetenv/resetenv keywords. - */ - if (backup_env() != 0) - return -1; - - /* temporary create environment variables with default - * values to ease user configuration. Do not forget to - * unset them after the list_for_each_entry loop. - */ - setenv("HAPROXY_HTTP_LOG_FMT", default_http_log_format, 1); - setenv("HAPROXY_HTTP_CLF_LOG_FMT", clf_http_log_format, 1); - setenv("HAPROXY_HTTPS_LOG_FMT", default_https_log_format, 1); - setenv("HAPROXY_TCP_LOG_FMT", default_tcp_log_format, 1); - setenv("HAPROXY_TCP_CLF_LOG_FMT", clf_tcp_log_format, 1); - setenv("HAPROXY_BRANCH", PRODUCT_BRANCH, 1); list_for_each_entry_safe(cfg, cfg_tmp, &cfg_cfgfiles, list) { - int ret; cfg->size = load_cfg_in_mem(cfg->filename, &cfg->content); if (cfg->size < 0) @@ -1209,16 +1189,51 @@ static int read_cfg(char *progname) ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n"); goto err; } + } + + setenv("HAPROXY_CFGFILES", env_cfgfiles, 1); + free(env_cfgfiles); + + return 0; +err: + free(env_cfgfiles); + return -1; + +} + +/* Calls parser for each config file from cfg_cfgfiles list. Returns -1, if we + * are run out of memory, can't apply default path or when the parser function + * returns some fatal errors. + * Otherwise, it returns an err_code, which may contain 0 (OK) or ERR_WARN, + * ERR_ALERT. + */ +static int read_cfg(char *progname) +{ + struct cfgfile *cfg; + int err_code = 0; + + /* temporary create environment variables with default + * values to ease user configuration. Do not forget to + * unset them after the list_for_each_entry loop. + */ + setenv("HAPROXY_HTTP_LOG_FMT", default_http_log_format, 1); + setenv("HAPROXY_HTTP_CLF_LOG_FMT", clf_http_log_format, 1); + setenv("HAPROXY_HTTPS_LOG_FMT", default_https_log_format, 1); + setenv("HAPROXY_TCP_LOG_FMT", default_tcp_log_format, 1); + setenv("HAPROXY_TCP_CLF_LOG_FMT", clf_tcp_log_format, 1); + setenv("HAPROXY_BRANCH", PRODUCT_BRANCH, 1); + list_for_each_entry(cfg, &cfg_cfgfiles, list) { + int ret; ret = parse_cfg(cfg); if (ret == -1) - goto err; + return -1; if (ret & (ERR_ABORT|ERR_FATAL)) ha_alert("Error(s) found in configuration file : %s\n", cfg->filename); err_code |= ret; if (err_code & ERR_ABORT) - goto err; + return -1; } /* remove temporary environment variables. */ unsetenv("HAPROXY_BRANCH"); @@ -1233,16 +1248,10 @@ static int read_cfg(char *progname) */ if (err_code & (ERR_ABORT|ERR_FATAL)) { ha_alert("Fatal errors found in configuration.\n"); - goto err; + return -1; } - setenv("HAPROXY_CFGFILES", env_cfgfiles, 1); - free(env_cfgfiles); - return err_code; -err: - free(env_cfgfiles); - return -1; } /* @@ -2037,15 +2046,24 @@ static void init(int argc, char **argv) usermsgs_clr("config"); - if (!(global.mode & MODE_MWORKER)) { + /* load configs and read only the keywords with KW_DISCOVERY flag */ + global.mode |= MODE_DISCOVERY; + + ret = load_cfg(progname); + if (ret == 0) { + /* read only global section in discovery mode */ ret = read_cfg(progname); - /* free memory to store config file content */ - list_for_each_entry_safe(cfg, cfg_tmp, &cfg_cfgfiles, list) + } + if (ret < 0) { + list_for_each_entry_safe(cfg, cfg_tmp, &cfg_cfgfiles, list) { ha_free(&cfg->content); - if (ret < 0) - exit(1); + ha_free(&cfg->filename); + } + exit(1); } + global.mode &= ~MODE_DISCOVERY; + if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) { ha_alert("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n"); exit(EXIT_FAILURE); @@ -2194,6 +2212,20 @@ static void init(int argc, char **argv) } } + /* worker, daemon, foreground mode reads the rest of the config */ + if (!(global.mode & MODE_MWORKER)) { + if (read_cfg(progname) < 0) { + list_for_each_entry_safe(cfg, cfg_tmp, &cfg_cfgfiles, list) { + ha_free(&cfg->content); + ha_free(&cfg->filename); + } + exit(1); + } + /* all sections have been parsed */ + list_for_each_entry_safe(cfg, cfg_tmp, &cfg_cfgfiles, list) + ha_free(&cfg->content); + } + /* destroy unreferenced defaults proxies */ proxy_destroy_all_unref_defaults();