From fab0fdce981149a4e3172f2b81113f505f415595 Mon Sep 17 00:00:00 2001 From: William Lallemand Date: Tue, 9 Nov 2021 18:01:22 +0100 Subject: [PATCH] MEDIUM: mworker: reexec in waitpid mode after successful loading Use the waitpid mode after successfully loading the configuration, this way the memory will be freed in the master, and will preserve the memory. This will be useful when doing a reload with a configuration which has large maps or a lot of SSL certificates, avoiding an OOM because too much memory was allocated in the master. --- src/haproxy.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/haproxy.c b/src/haproxy.c index 4f112f4841..b404f173a1 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -690,7 +690,7 @@ static void get_cur_unixsocket() * When called, this function reexec haproxy with -sf followed by current * children PIDs and possibly old children PIDs if they didn't leave yet. */ -void mworker_reload() +static void mworker_reexec() { char **next_argv = NULL; int old_argc = 0; /* previous number of argument */ @@ -791,6 +791,19 @@ void mworker_reload() return; } +/* reexec haproxy in waitmode */ +static void mworker_reexec_waitmode() +{ + setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1); + mworker_reexec(); +} + +/* reload haproxy and emit a warning */ +void mworker_reload() +{ + mworker_reexec(); +} + static void mworker_loop() { @@ -801,7 +814,6 @@ static void mworker_loop() /* Busy polling makes no sense in the master :-) */ global.tune.options &= ~GTUNE_BUSY_POLLING; - master = 1; signal_unregister(SIGTTIN); signal_unregister(SIGTTOU); @@ -847,11 +859,9 @@ void reexec_on_failure() { if (!atexit_flag) return; - - setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1); - ha_warning("Reexecuting Master process in waitpid mode\n"); - mworker_reload(); + usermsgs_clr(NULL); + mworker_reexec_waitmode(); } @@ -3232,6 +3242,7 @@ int main(int argc, char **argv) if (in_parent) { if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) { + master = 1; if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) && (global.mode & MODE_DAEMON)) { @@ -3243,7 +3254,14 @@ int main(int argc, char **argv) global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */ } - mworker_loop(); + if (global.mode & MODE_MWORKER_WAIT) { + /* only the wait mode handles the master CLI */ + mworker_loop(); + } else { + + /* if not in wait mode, reload in wait mode to free the memory */ + mworker_reexec_waitmode(); + } /* should never get there */ exit(EXIT_FAILURE); }