]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: backend: never try to attach to a mux having no more stream available
authorWilly Tarreau <w@1wt.eu>
Thu, 24 Jan 2019 17:22:19 +0000 (18:22 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 24 Jan 2019 18:06:43 +0000 (19:06 +0100)
The code dealing with idle connections used to check the number of streams
available on the connection only to unlink the connection from the idle
list. But this still resulted in too many streams reusing the same connection
when they were already attached to it.

We must detect that there is no more room and refrain from using this
connection at all, and instead fall back to the no-reuse case. Ideally
we should try to search among other idle connections, but for a backport
let's stay safe.

This must be backported to 1.9.

src/backend.c

index aef58c2b94d9e3bd678098e5a64161e2a74e36c4..59324538d63e876bddf3cda81fc0e9850b93f94d 100644 (file)
@@ -1297,26 +1297,40 @@ int connect_server(struct stream *s)
                }
        }
 
-       if (!reuse) {
-               srv_conn = conn_new();
-               srv_cs = NULL;
-       } else {
+       if (reuse) {
                /* We already created a cs earlier when using http_proxy, so
                 * only create a new one if we don't have one already.
                 */
                if (!srv_cs) {
-                       if (srv_conn->mux->avail_streams(srv_conn) <= 1) {
+                       int avail = srv_conn->mux->avail_streams(srv_conn);
+
+                       if (avail <= 1) {
                                /* No more streams available, remove it from the list */
                                LIST_DEL(&srv_conn->list);
                                LIST_INIT(&srv_conn->list);
                        }
-                       srv_cs = srv_conn->mux->attach(srv_conn, s->sess);
-                       if (srv_cs)
-                               si_attach_cs(&s->si[1], srv_cs);
+
+                       if (avail >= 1) {
+                               srv_cs = srv_conn->mux->attach(srv_conn, s->sess);
+                               if (srv_cs)
+                                       si_attach_cs(&s->si[1], srv_cs);
+                               else
+                                       srv_conn = NULL;
+                       }
                        else
                                srv_conn = NULL;
                }
+               /* otherwise srv_conn is left intact */
        }
+       else
+               srv_conn = NULL;
+
+       /* no reuse or failed to reuse the connection above, pick a new one */
+       if (!srv_conn) {
+               srv_conn = conn_new();
+               srv_cs = NULL;
+       }
+
        if (srv_conn && old_conn != srv_conn) {
                if (srv_conn->owner)
                        session_unown_conn(srv_conn->owner, srv_conn);