BUG/MEDIUM: sink: fix unexpected double postinit of sink backend

Willy experienced an unexpected behavior with the config below:

    global
        stats socket :1514

    ring buf1
        server srv1 127.0.0.1:1514

Indeed, haproxy would connect to the ring server twice since commit 23e5f18b
("MEDIUM: sink: change the sink mode type to PR_MODE_SYSLOG"), and one of the
connection would report errors.

The reason behind is is, despite the above commit saying no change of behavior
is expected, with the sink forward_px proxy now being set with PR_MODE_SYSLOG,
postcheck_log_backend() was being automatically executed in addition to the
manual cfg_post_parse_ring() function for each "ring" section. The consequence
is that sink_finalize() was called twice for a given "ring" section, which
means the connection init would be triggered twice.. which in turn resulted in
the behavior described above, plus possible unexpected side-effects.

To fix the issue, when we create the forward_px proxy, we now set the
PR_CAP_INT capability on it to tell haproxy not to automatically manage the
proxy (ie: to skip the automatic log backend postinit), because we are about
to manually manage the proxy from the sink API.

No backport needed, this bug is specific to 3.3
This commit is contained in:
Aurelien DARRAGON 2025-09-18 13:29:53 +02:00
parent 79ef362d9e
commit 40eb1dd135
2 changed files with 7 additions and 4 deletions

View File

@ -1350,8 +1350,8 @@ static int postcheck_log_backend(struct proxy *be)
int err_code = ERR_NONE;
int target_type = -1; // -1 is unused in log_tgt enum
if (!(be->cap & PR_CAP_BE) || be->mode != PR_MODE_SYSLOG ||
(be->flags & (PR_FL_DISABLED|PR_FL_STOPPED)))
if ((be->cap & PR_CAP_INT) || !(be->cap & PR_CAP_BE) ||
be->mode != PR_MODE_SYSLOG || (be->flags & (PR_FL_DISABLED|PR_FL_STOPPED)))
return ERR_NONE; /* nothing to do */
err_code |= _postcheck_log_backend_compat(be);

View File

@ -842,8 +842,11 @@ static struct sink *sink_new_ringbuf(const char *id, const char *description,
struct sink *sink;
struct proxy *p = NULL; // forward_px
/* allocate new proxy to handle forwards */
p = alloc_new_proxy(id, PR_CAP_BE, err_msg);
/* allocate new proxy to handle forwards, mark it as internal proxy
* because we don't want haproxy to do the automatic syslog backend
* init, instead we will manage it by hand
*/
p = alloc_new_proxy(id, PR_CAP_BE|PR_CAP_INT, err_msg);
if (!p)
goto err;