]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: release lock on idle conn killing on reached pool high count
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 23 Mar 2021 09:44:43 +0000 (10:44 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 25 Mar 2021 10:55:35 +0000 (11:55 +0100)
Release the lock before calling mux destroy in connect_server when
trying to kill an idle connection because the pool high count has been
reached.

The lock must be released because the mux destroy will call
srv_release_conn which also takes the lock to remove the connection from
the tree. As the connection was already deleted from the tree at this
stage, it is safe to release the lock, and the removal in
srv_release_conn will be a noop.

It does not need to be backported because it is only present in the
current release. It has been introduced by
    5c7086f6b06d546c5800486ed9e4bb8d8d471e09
    MEDIUM: connection: protect idle conn lists with locks

src/backend.c

index 80f00f2586ea03061c89bbc2f03a5a91153d8b2b..3cc7adc37efe0fd0c26cf037242e6bdf60f65f24 100644 (file)
@@ -1426,9 +1426,17 @@ int connect_server(struct stream *s)
                        conn_node = ebmb_entry(node, struct conn_hash_node, node);
                        tokill_conn = conn_node->conn;
                        ebmb_delete(node);
+                       HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
+
+                       /* Release the idle lock before calling mux->destroy.
+                        * It will in turn call srv_release_conn through
+                        * conn_free which also uses it.
+                        */
                        tokill_conn->mux->destroy(tokill_conn->ctx);
                }
-               HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
+               else {
+                       HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
+               }
 
                /* If not, iterate over other thread's idling pool, and try to grab one */
                if (!tokill_conn) {