]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mworker: restore initial env before wait mode
authorValentine Krasnobaeva <vkrasnobaeva@haproxy.com>
Wed, 21 Aug 2024 17:07:22 +0000 (19:07 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 23 Aug 2024 15:06:59 +0000 (17:06 +0200)
This patch is the follow-up of 1811d2a6ba (MINOR: tools: add helpers to
backup/clean/restore env).

In order to avoid unexpected behaviour in master-worker mode during the process
reload with a new configuration, when the old one has contained '*env' keywords,
let's backup its initial environment before calling parse_cfg() and let's clean
and restore it in the context of master process, just before it enters in a wait
polling loop.

This will garantee that new workers will have a new updated environment and not
the previous one inherited from the master, which does not read the configuration,
when it's in a wait-mode.

include/haproxy/global.h
src/haproxy.c

index 561802a83733da3978f5b0b54233461127f73b8d..37a460223ab565762e22a044e59f834253e9db3b 100644 (file)
@@ -48,6 +48,7 @@ extern int master; /* 1 if in master, 0 otherwise */
 extern int atexit_flag;
 extern unsigned char boot_seed[20];  // per-boot random seed (160 bits initially)
 extern THREAD_LOCAL struct buffer trash;
+extern char **init_env;
 
 struct proxy;
 struct server;
index 8946c657ba405ae199a8024c3644b74c24b23891..218040c1a5bcccdc96bf5393576d99de8caf944d 100644 (file)
@@ -154,6 +154,7 @@ char *build_features = "";
 /* list of config files */
 static struct list cfg_cfgfiles = LIST_HEAD_INIT(cfg_cfgfiles);
 int  pid;                      /* current process id */
+char **init_env;
 
 static unsigned long stopping_tgroup_mask; /* Thread groups acknowledging stopping */
 
@@ -1170,7 +1171,9 @@ next_dir_entry:
 /* 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.
+ * 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.
  */
 static int read_cfg(char *progname)
 {
@@ -1184,6 +1187,12 @@ 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.
@@ -2654,6 +2663,7 @@ void deinit(void)
        struct post_proxy_check_fct *ppcf, *ppcfb;
        struct pre_check_fct *prcf, *prcfb;
        struct cfg_postparser *pprs, *pprsb;
+       char **tmp = init_env;
        int cur_fd;
 
        /* the user may want to skip this phase */
@@ -2851,6 +2861,14 @@ void deinit(void)
        vars_prune(&proc_vars, NULL, NULL);
        pool_destroy_all();
        deinit_pollers();
+
+       /* free env variables backup */
+       while (*tmp) {
+               free(*tmp);
+               tmp++;
+       }
+       free(init_env);
+
 } /* end deinit() */
 
 __attribute__((noreturn)) void deinit_and_exit(int status)
@@ -3623,7 +3641,18 @@ int main(int argc, char **argv)
                                        if (global.tune.options & GTUNE_USE_SYSTEMD)
                                                sd_notifyf(0, "READY=1\nMAINPID=%lu\nSTATUS=Ready.\n", (unsigned long)getpid());
 #endif
-                                       /* if not in wait mode, reload in wait mode to free the memory */
+                                       /* if not in wait mode, restore initial environment (before parsing the config) and
+                                        * reload in wait mode to free the memory. The initial process environment should
+                                        * be restored here, preceded by clean_env(), which do the same job as clearenv().
+                                        * Otherwise, we will lost HAPROXY_LOAD_SUCCESS, HAPROXY_MWORKER_WAIT_ONLY and
+                                        * HAPROXY_MWORKER_REEXEC variables, which will be set further.
+                                        */
+                                       if (clean_env() != 0)
+                                               exit(EXIT_FAILURE);
+
+                                       if (restore_env() != 0)
+                                               exit(EXIT_FAILURE);
+
                                        setenv("HAPROXY_LOAD_SUCCESS", "1", 1);
                                        ha_notice("Loading success.\n");
                                        proc_self->failedreloads = 0; /* reset the number of failure */