From 97490a7789f39d704193e2146131cf5574a755ff Mon Sep 17 00:00:00 2001 From: William Lallemand Date: Tue, 6 Jan 2026 13:59:41 +0100 Subject: [PATCH] BUG/MEDIUM: mworker: can't use signals after a failed reload In issue #3229 it was reported that the master couldn't reload after a failed reload following a wrong configuration. It is still possible to do a reload using the "reload" command of the master CLI. But every signals are blocked. The problem was introduced in 709cde6d0 ("BUG/MEDIUM: mworker: signals inconsistencies during startup and reload") which fixes the blocking of signals during the reload. However the patch missed a case, indeed, the run_master_in_recovery_mode() is not being called when the worker failed to parse the configuration, it is only failing when the master is failing. To handle this case, the mworker_unblock_signals() function must be called upon mworker_on_new_child_failure(). But since this is called in an haproxy signal handler it would mess with the signals. Instead, the patch adds a task which is started by the signal handler, and restores the signals outside of it. This must be backported as far as 3.1. --- src/mworker.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/mworker.c b/src/mworker.c index cdf9a9332..956ffc041 100644 --- a/src/mworker.c +++ b/src/mworker.c @@ -508,6 +508,14 @@ void mworker_catch_sigterm(struct sig_handler *sh) mworker_kill(sig); } +/* handle operations that can't be done in the signal handler */ +static struct task *mworker_task_child_failure(struct task *task, void *context, unsigned int state) +{ + mworker_unblock_signals(); + task_destroy(task); + return NULL; +} + /* * Performs some routines for the worker process, which has failed the reload, * updates the global load_status. @@ -515,6 +523,7 @@ void mworker_catch_sigterm(struct sig_handler *sh) static void mworker_on_new_child_failure(int exitpid, int status) { struct mworker_proc *child; + struct task *t; /* increment the number of failed reloads */ list_for_each_entry(child, &proc_list, list) { @@ -531,6 +540,15 @@ static void mworker_on_new_child_failure(int exitpid, int status) * the READY=1 signal still need to be sent */ if (global.tune.options & GTUNE_USE_SYSTEMD) sd_notify(0, "READY=1\nSTATUS=Reload failed!\n"); + + /* call a task to unblock the signals from outside the sig handler */ + if ((t = task_new_here()) == NULL) { + ha_warning("Can't restore HAProxy signals!\n"); + return; + } + + t->process = mworker_task_child_failure; + task_wakeup(t, TASK_WOKEN_MSG); } /*