]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: sink: fix unexpected double postinit of sink backend
authorAurelien DARRAGON <adarragon@haproxy.com>
Thu, 18 Sep 2025 11:29:53 +0000 (13:29 +0200)
committerAurelien DARRAGON <adarragon@haproxy.com>
Thu, 18 Sep 2025 14:49:29 +0000 (16:49 +0200)
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

src/log.c
src/sink.c

index a1cc0bc3e685ea339ad0ca3a6f449da293a8d215..c95905ee202adbad6991e06a166c1367ba8bb003 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -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);
index 4485e95e5df6f367122bd39a9d20c8c0e818a768..7a31d38273a04d374f9e94d141419ac541bc9406 100644 (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;