]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MINOR: stream: Fix custom max-retries initialization when setting backend
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 7 Jul 2026 08:07:31 +0000 (10:07 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 8 Jul 2026 06:52:07 +0000 (08:52 +0200)
It is possible to overwrite the configured max-retries value with the
"set-retries" action. However there is an issue with the listeners. When the
backend is set, this value is reset with the backend value. However, when
the backend is unchanged, the custom value must be preserved.

To fix the issue, when the stream is created, we set the max-retries to the
listener value. It remains 0 for pure-frontend. And the backend value is
used only if it is not the same proxy.

The documentation of set-retries action was improved.

This patch should be backported as far as 3.2.

doc/configuration.txt
src/stream.c

index 4e269c488a8acb9ba8ced948d8ad891ed17c6ad6..26137459ee4741c6e81b1c40bb25c3b78730da0c 100644 (file)
@@ -16591,7 +16591,11 @@ set-retries <int> | <epxr>
 
   Note that this action is only relevant on the backend side and thus this rule
   is only available for the proxies with backend capability. It is also not
-  allowed in "defaults" sections.
+  allowed in "defaults" sections. When the action is used for a listener, it is
+  evaluated in the frontend context. So retries value is conserved only if
+  stream is not routed to a different backend, via a use-backend rule for
+  instance. Otherwise the default retries value of the selected backend will be
+  preset.
 
   Example:
     tcp-request content set-retries 3
index 24cdb723061c21ab1ff0b914d046c582e5a3e906..ccf0ea993d2562d62c5ee59f4c63d27c606be126 100644 (file)
@@ -436,7 +436,7 @@ void *stream_new(struct session *sess, struct stconn *sc, struct buffer *input)
        s->task = t;
        s->pending_events = s->new_events = STRM_EVT_NONE;
        s->conn_retries = 0;
-       s->max_retries = 0;
+       s->max_retries = ((sess->fe->cap & PR_CAP_BE) ? sess->fe->conn_retries : 0);
        s->conn_exp = TICK_ETERNITY;
        s->conn_err_type = STRM_ET_NONE;
        s->prev_conn_state = SC_ST_INI;
@@ -1261,8 +1261,6 @@ static int process_switching_rules(struct stream *s, struct channel *req, int an
                        goto sw_failed;
        }
 
-       /* Se the max connection retries for the stream. may be overwritten later */
-       s->max_retries = s->be->conn_retries;
        if (fe == s->be) {
                /* we don't want to run the TCP or HTTP filters again if the backend has not changed */
                s->req.analysers &= ~AN_REQ_INSPECT_BE;
@@ -1270,6 +1268,8 @@ static int process_switching_rules(struct stream *s, struct channel *req, int an
                s->req.analysers &= ~AN_REQ_FLT_START_BE;
        }
        else {
+               /* Set the max connection retries for the stream. may be overwritten later */
+               s->max_retries = s->be->conn_retries;
                s->scb->ioto = TICK_ETERNITY;
                s->connect_timeout = TICK_ETERNITY;
                s->queue_timeout = TICK_ETERNITY;