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.
This commit is contained in:
William Lallemand 2026-01-06 13:59:41 +01:00
parent 56fd0c1a5c
commit 97490a7789

View File

@ -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);
}
/*