From: Willy Tarreau Date: Tue, 15 Sep 2026 11:45:35 +0000 (+0200) Subject: MINOR: mworker: assign a unique ID to the master process X-Git-Tag: v3.5-dev7~11 X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=fbe37fa504b54f1bda9a05bf022c102b74244aab;p=haproxy.git MINOR: mworker: assign a unique ID to the master process The master process now has a unique identifier, either generated at boot as a time-ordered UUID (version 7), or inherited from the HAPROXY_MASTER_ID environment variable when a valid one is already set there (inherited from a previous master instance). An invalid value is simply replaced by a generated one, since there is generally nothing the user can do about it. The identifier is exported to the environment so that it is both preserved by the next master upon reload (re-exec) and visible from the worker, where it may be referenced as "$HAPROXY_MASTER_ID" from the configuration. The format is validated using guid_is_valid_fmt() so that it is exactly the same as the one of the proxies' and servers' "guid": at most 127 characters among letters, digits, '.', ':', '-' and '_'. Note that both mworker_reexec() and the worker restore their initial environment before going further, so the variable has to be set again after that point, hence the two extra setenv() calls, just like for a few other such variables. --- diff --git a/doc/configuration.txt b/doc/configuration.txt index 5fe5e4bfb..7740b52e5 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -980,6 +980,7 @@ Some variables are marked as not usable and not modifiable: * HAPROXY_MWORKER * HAPROXY_CLI * HAPROXY_MASTER_CLI + * HAPROXY_MASTER_ID * HAPROXY_LOCALPEER Their values are undefined during configuration parsing, they are set later @@ -1001,6 +1002,7 @@ modes: | HAPROXY_MWORKER | | | | | X | X | | HAPROXY_CLI | | | | | | X | | HAPROXY_MASTER_CLI | | | | | X | | + | HAPROXY_MASTER_ID | | X | | | X | X | | HAPROXY_LOCALPEER | | X | | | | X | | HAPROXY_HTTP_LOG_FMT | | X | | X | | | | HAPROXY_HTTP_CLF_LOG_FMT | | X | | X | | | @@ -1060,6 +1062,15 @@ The variables in question are the following: * HAPROXY_MASTER_CLI: In master-worker mode, listeners addresses of the master CLI, separated by semicolons. + * HAPROXY_MASTER_ID: In master-worker mode, unique identifier of the master + process. A time-ordered UUID (version 7) is generated when the master + starts, unless a valid identifier is already present in the environment; an + invalid one is simply replaced by a generated one. It is then passed to the + next master upon reload, so that it remains stable for the whole life of + the master, and it is also exposed to the worker. Its format is the same as + the one of the proxies' and servers' "guid": at most 127 characters among + letters, digits, '.', ':', '-' and '_'. + * HAPROXY_STARTUP_VERSION: contains the version used to start, in master- worker mode this is the version which was used to start the master, even after updating the binary and reloading. diff --git a/include/haproxy/global-t.h b/include/haproxy/global-t.h index fd27e69ee..6d26cb2fc 100644 --- a/include/haproxy/global-t.h +++ b/include/haproxy/global-t.h @@ -161,6 +161,7 @@ struct global { char *chroot; char *pidfile; char *node, *desc; /* node name & description */ + char *master_id; /* master process' unique ID, preserved upon reload */ int localpeer_cmdline; /* whether or not the commandline "-L" was set */ int fd_hard_limit; /* hard limit on ulimit-n : 0=unset */ struct buffer log_tag; /* name for syslog */ diff --git a/src/haproxy.c b/src/haproxy.c index d305d17c0..ffe0d138b 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -2882,6 +2882,7 @@ void deinit(void) ha_free(&global.pidfile); ha_free(&global.node); ha_free(&global.desc); + ha_free(&global.master_id); ha_free(&oldpids); ha_free(&old_argv); ha_free(&localpeer); @@ -3613,6 +3614,12 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } setenv("HAPROXY_MWORKER", "1", 1); + + /* restore_env() above has dropped it, put it back so + * that the worker's config may reference it. + */ + if (global.master_id) + setenv("HAPROXY_MASTER_ID", global.master_id, 1); } /* localpeer default value could be redefined via 'localpeer' keyword diff --git a/src/mworker.c b/src/mworker.c index 28028bc57..dc043ceae 100644 --- a/src/mworker.c +++ b/src/mworker.c @@ -21,11 +21,13 @@ #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -356,6 +358,13 @@ static void mworker_reexec(int hardreload) setenv("HAPROXY_MWORKER_REEXEC", "1", 1); + /* restore_env() above has dropped it, but the next master must keep + * the ID of the current one, which is the whole point of passing it + * through the environment. + */ + if (global.master_id) + setenv("HAPROXY_MASTER_ID", global.master_id, 1); + mworker_proc_list_to_env(); /* put the children description in the env */ /* during the reload we must ensure that every FDs that can't be @@ -1178,9 +1187,32 @@ void mworker_create_master_cli(void) void mworker_prepare_master(void) { struct mworker_proc *tmproc; + char uuid[40]; + const char *id; setenv("HAPROXY_MWORKER", "1", 1); + /* Assign a unique ID to this master process. It is taken from the + * environment when a valid one is found there, which happens either on + * reload since the previous master passes its own to us, or when an + * orchestrator wants to force it. Otherwise a time-ordered UUID v7 is + * generated. This way it identifies this master for its whole life. + */ + id = getenv("HAPROXY_MASTER_ID"); + if (!id || !guid_is_valid_fmt(id, NULL)) { + struct buffer buf = b_make(uuid, sizeof(uuid), 0, 0); + + ha_generate_uuid_v7(&buf); + id = uuid; + } + + global.master_id = strdup(id); + if (!global.master_id) { + ha_alert("Cannot allocate memory for the master's ID.\n"); + exit(EXIT_FAILURE); + } + setenv("HAPROXY_MASTER_ID", global.master_id, 1); + if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) { tmproc = mworker_proc_new();