REORG: startup: move mworker_reexec and mworker_reload in mworker.c

Let's move mworker_reexec() and mworker_reload() in mworker.c. mworker_reload()
is called only within the functions, which are already in mworker.c. So, this
reorganization allows to declare mworker_reload() as a static.
This commit is contained in:
Valentine Krasnobaeva 2024-11-25 12:04:35 +01:00 committed by William Lallemand
parent 0c7b93eb1d
commit dee247c14e
4 changed files with 176 additions and 175 deletions

View File

@ -51,6 +51,8 @@ extern unsigned char boot_seed[20]; // per-boot random seed (160 bits initially
extern THREAD_LOCAL struct buffer trash;
extern char **init_env;
extern char *progname;
extern char **old_argv;
extern const char *old_unixsocket;
struct proxy;
struct server;
@ -68,7 +70,6 @@ int compare_current_version(const char *version);
void display_version();
void mworker_accept_wrapper(int fd);
void mworker_reload(int hardreload);
/* to be used with warned and WARN_* */
static inline int already_warned(unsigned int warning)

View File

@ -14,6 +14,7 @@
#ifndef _HAPROXY_MWORKER_H_
#define _HAPROXY_MWORKER_H_
#include <haproxy/limits.h>
#include <haproxy/mworker-t.h>
#include <haproxy/signal-t.h>

View File

@ -240,7 +240,7 @@ static int *oldpids = NULL;
int oldpids_sig; /* use USR1 or TERM */
/* Path to the unix socket we use to retrieve listener sockets from the old process */
static const char *old_unixsocket;
const char *old_unixsocket;
int atexit_flag = 0;
@ -253,7 +253,7 @@ char hostname[MAX_HOSTNAME_LEN];
char *localpeer = NULL;
static char *kwd_dump = NULL; // list of keyword dumps to produce
static char **old_argv = NULL; /* previous argv but cleaned up */
char **old_argv = NULL; /* previous argv but cleaned up */
struct list proc_list = LIST_HEAD_INIT(proc_list);
@ -703,178 +703,6 @@ int delete_oldpid(int pid)
return 0;
}
/*
* When called, this function reexec haproxy with -sf followed by current
* children PIDs and possibly old children PIDs if they didn't leave yet.
*/
static void mworker_reexec(int hardreload)
{
char **next_argv = NULL;
int old_argc = 0; /* previous number of argument */
int next_argc = 0;
int i = 0;
char *msg = NULL;
struct rlimit limit;
struct mworker_proc *current_child = NULL;
int x_off = 0; /* disable -x by putting -x /dev/null */
mworker_block_signals();
/* restore initial environment (before parsing the config) and do re-exec.
* The initial process environment should be restored here, preceded by
* clean_env(), which do the same job as clearenv().
* Otherwise, after the re-exec we will start the new worker in the
* environment modified by '*env' keywords from the previous configuration,
* i.e. existed before the reload.
*/
if (clean_env() != 0) {
ha_alert("Master encountered a non-recoverable error, exiting.\n");
exit(EXIT_FAILURE);
}
if (restore_env() != 0) {
ha_alert("Master encountered a non-recoverable error, exiting.\n");
exit(EXIT_FAILURE);
}
setenv("HAPROXY_MWORKER_REEXEC", "1", 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
* reuse (ie those that are not referenced in the proc_list)
* are closed or they will leak. */
/* close the listeners FD */
mworker_cli_proxy_stop();
if (fdtab)
deinit_pollers();
#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
/* close random device FDs */
RAND_keep_random_devices_open(0);
#endif
/* restore the initial FD limits */
limit.rlim_cur = rlim_fd_cur_at_boot;
limit.rlim_max = rlim_fd_max_at_boot;
if (raise_rlim_nofile(&limit, &limit) != 0) {
ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
(unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
}
/* compute length */
while (old_argv[old_argc])
old_argc++;
/* 1 for haproxy -sf, 2 for -x /socket */
next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
sizeof(*next_argv));
if (next_argv == NULL)
goto alloc_error;
/* copy the program name */
next_argv[next_argc++] = old_argv[0];
/* we need to reintroduce /dev/null every time */
if (old_unixsocket && strcmp(old_unixsocket, "/dev/null") == 0)
x_off = 1;
/* insert the new options just after argv[0] in case we have a -- */
/* add -sf <PID>* to argv */
if (mworker_child_nb() > 0) {
struct mworker_proc *child;
if (hardreload)
next_argv[next_argc++] = "-st";
else
next_argv[next_argc++] = "-sf";
list_for_each_entry(child, &proc_list, list) {
if (!(child->options & PROC_O_LEAVING) && (child->options & PROC_O_TYPE_WORKER))
current_child = child;
if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1)
continue;
if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
goto alloc_error;
msg = NULL;
}
}
if (!x_off && current_child) {
/* add the -x option with the socketpair of the current worker */
next_argv[next_argc++] = "-x";
if ((next_argv[next_argc++] = memprintf(&msg, "sockpair@%d", current_child->ipc_fd[0])) == NULL)
goto alloc_error;
msg = NULL;
}
if (x_off) {
/* if the cmdline contained a -x /dev/null, continue to use it */
next_argv[next_argc++] = "-x";
next_argv[next_argc++] = "/dev/null";
}
/* copy the previous options */
for (i = 1; i < old_argc; i++)
next_argv[next_argc++] = old_argv[i];
/* need to withdraw MODE_STARTING from master, because we have to free
* the startup logs ring here, see more details in print_message()
*/
global.mode &= ~MODE_STARTING;
startup_logs_free(startup_logs);
signal(SIGPROF, SIG_IGN);
execvp(next_argv[0], next_argv);
ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
ha_free(&next_argv);
return;
alloc_error:
ha_free(&next_argv);
ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
return;
}
/* reload haproxy and emit a warning */
void mworker_reload(int hardreload)
{
struct mworker_proc *child;
struct per_thread_deinit_fct *ptdf;
ha_notice("Reloading HAProxy%s\n", hardreload?" (hard-reload)":"");
/* close the poller FD and the thread waker pipe FD */
list_for_each_entry(ptdf, &per_thread_deinit_list, list)
ptdf->fct();
/* increment the number of reloads, child->reloads is checked in
* mworker_env_to_proc_list() (after reload) in order to set
* PROC_O_LEAVING flag for the process
*/
list_for_each_entry(child, &proc_list, list) {
child->reloads++;
}
if (global.tune.options & GTUNE_USE_SYSTEMD) {
struct timespec ts;
(void)clock_gettime(CLOCK_MONOTONIC, &ts);
sd_notifyf(0,
"RELOADING=1\n"
"STATUS=Reloading Configuration.\n"
"MONOTONIC_USEC=%" PRIu64 "\n",
(ts.tv_sec * 1000000ULL + ts.tv_nsec / 1000ULL));
}
mworker_reexec(hardreload);
}
/*
* Exit with an error message upon a master recovery mode failure.
*/

View File

@ -294,6 +294,177 @@ void mworker_broadcast_signal(struct sig_handler *sh)
mworker_kill(sh->arg);
}
/*
* When called, this function reexec haproxy with -sf followed by current
* children PIDs and possibly old children PIDs if they didn't leave yet.
*/
static void mworker_reexec(int hardreload)
{
char **next_argv = NULL;
int old_argc = 0; /* previous number of argument */
int next_argc = 0;
int i = 0;
char *msg = NULL;
struct rlimit limit;
struct mworker_proc *current_child = NULL;
int x_off = 0; /* disable -x by putting -x /dev/null */
mworker_block_signals();
/* restore initial environment (before parsing the config) and do re-exec.
* The initial process environment should be restored here, preceded by
* clean_env(), which do the same job as clearenv().
* Otherwise, after the re-exec we will start the new worker in the
* environment modified by '*env' keywords from the previous configuration,
* i.e. existed before the reload.
*/
if (clean_env() != 0) {
ha_alert("Master encountered a non-recoverable error, exiting.\n");
exit(EXIT_FAILURE);
}
if (restore_env() != 0) {
ha_alert("Master encountered a non-recoverable error, exiting.\n");
exit(EXIT_FAILURE);
}
setenv("HAPROXY_MWORKER_REEXEC", "1", 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
* reuse (ie those that are not referenced in the proc_list)
* are closed or they will leak. */
/* close the listeners FD */
mworker_cli_proxy_stop();
if (fdtab)
deinit_pollers();
#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
/* close random device FDs */
RAND_keep_random_devices_open(0);
#endif
/* restore the initial FD limits */
limit.rlim_cur = rlim_fd_cur_at_boot;
limit.rlim_max = rlim_fd_max_at_boot;
if (raise_rlim_nofile(&limit, &limit) != 0) {
ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
(unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
}
/* compute length */
while (old_argv[old_argc])
old_argc++;
/* 1 for haproxy -sf, 2 for -x /socket */
next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
sizeof(*next_argv));
if (next_argv == NULL)
goto alloc_error;
/* copy the program name */
next_argv[next_argc++] = old_argv[0];
/* we need to reintroduce /dev/null every time */
if (old_unixsocket && strcmp(old_unixsocket, "/dev/null") == 0)
x_off = 1;
/* insert the new options just after argv[0] in case we have a -- */
/* add -sf <PID>* to argv */
if (mworker_child_nb() > 0) {
struct mworker_proc *child;
if (hardreload)
next_argv[next_argc++] = "-st";
else
next_argv[next_argc++] = "-sf";
list_for_each_entry(child, &proc_list, list) {
if (!(child->options & PROC_O_LEAVING) && (child->options & PROC_O_TYPE_WORKER))
current_child = child;
if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1)
continue;
if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
goto alloc_error;
msg = NULL;
}
}
if (!x_off && current_child) {
/* add the -x option with the socketpair of the current worker */
next_argv[next_argc++] = "-x";
if ((next_argv[next_argc++] = memprintf(&msg, "sockpair@%d", current_child->ipc_fd[0])) == NULL)
goto alloc_error;
msg = NULL;
}
if (x_off) {
/* if the cmdline contained a -x /dev/null, continue to use it */
next_argv[next_argc++] = "-x";
next_argv[next_argc++] = "/dev/null";
}
/* copy the previous options */
for (i = 1; i < old_argc; i++)
next_argv[next_argc++] = old_argv[i];
/* need to withdraw MODE_STARTING from master, because we have to free
* the startup logs ring here, see more details in print_message()
*/
global.mode &= ~MODE_STARTING;
startup_logs_free(startup_logs);
signal(SIGPROF, SIG_IGN);
execvp(next_argv[0], next_argv);
ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
ha_free(&next_argv);
return;
alloc_error:
ha_free(&next_argv);
ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
return;
}
/* reload haproxy and emit a warning */
static void mworker_reload(int hardreload)
{
struct mworker_proc *child;
struct per_thread_deinit_fct *ptdf;
ha_notice("Reloading HAProxy%s\n", hardreload?" (hard-reload)":"");
/* close the poller FD and the thread waker pipe FD */
list_for_each_entry(ptdf, &per_thread_deinit_list, list)
ptdf->fct();
/* increment the number of reloads, child->reloads is checked in
* mworker_env_to_proc_list() (after reload) in order to set
* PROC_O_LEAVING flag for the process
*/
list_for_each_entry(child, &proc_list, list) {
child->reloads++;
}
if (global.tune.options & GTUNE_USE_SYSTEMD) {
struct timespec ts;
(void)clock_gettime(CLOCK_MONOTONIC, &ts);
sd_notifyf(0,
"RELOADING=1\n"
"STATUS=Reloading Configuration.\n"
"MONOTONIC_USEC=%" PRIu64 "\n",
(ts.tv_sec * 1000000ULL + ts.tv_nsec / 1000ULL));
}
mworker_reexec(hardreload);
}
/*
* When called, this function reexec haproxy with -sf followed by current
* children PIDs and possibly old children PIDs if they didn't leave yet.