]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: backend: always release the previous connection into its own target srv_list
authorWilly Tarreau <w@1wt.eu>
Fri, 1 Feb 2019 10:54:23 +0000 (11:54 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 1 Feb 2019 10:58:33 +0000 (11:58 +0100)
There was a bug reported in issue #19 regarding the fact that haproxy
could mis-route requests to the wrong server. It turns out that when
switching to another server, the old connection was put back into the
srv_list corresponding to the stream's target instead of this connection's
target. Thus if this connection was later picked, it was pointing to the
wrong server.

The patch fixes this and also clarifies the assignment to srv_conn->target
so that it's clear we don't change it when picking it from the srv_list.

This must be backported to 1.9 only.

src/backend.c

index e4bd5bf54e00c39869fd973b9edec4d9cb9906a4..4340ba58a1d1d80ac092a883317f1f7c942d60b9 100644 (file)
@@ -1302,7 +1302,7 @@ int connect_server(struct stream *s)
                                        s->sess->idle_conns--;
                                session_unown_conn(s->sess, old_conn);
                                old_conn->owner = sess;
-                               if (!session_add_conn(sess, old_conn, s->target)) {
+                               if (!session_add_conn(sess, old_conn, old_conn->target)) {
                                        old_conn->owner = NULL;
                                        old_conn->mux->destroy(old_conn);
                                } else
@@ -1343,6 +1343,7 @@ int connect_server(struct stream *s)
        /* no reuse or failed to reuse the connection above, pick a new one */
        if (!srv_conn) {
                srv_conn = conn_new();
+               srv_conn->target = s->target;
                srv_cs = NULL;
        }
 
@@ -1350,7 +1351,7 @@ int connect_server(struct stream *s)
                if (srv_conn->owner)
                        session_unown_conn(srv_conn->owner, srv_conn);
                srv_conn->owner = s->sess;
-               if (!session_add_conn(s->sess, srv_conn, s->target)) {
+               if (!session_add_conn(s->sess, srv_conn, srv_conn->target)) {
                        /* If we failed to attach the connection, detach the
                         * conn_stream, possibly destroying the connection */
                        if (alloced_cs)
@@ -1374,9 +1375,6 @@ int connect_server(struct stream *s)
        }
 
        if (!conn_xprt_ready(srv_conn) && !srv_conn->mux) {
-               /* the target was only on the stream, assign it to the SI now */
-               srv_conn->target = s->target;
-
                /* set the correct protocol on the output stream interface */
                if (srv)
                        conn_prepare(srv_conn, protocol_by_family(srv_conn->addr.to.ss_family), srv->xprt);