]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: mux-fcgi: Don't add private connections in available connection list
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 1 Jul 2020 13:51:46 +0000 (15:51 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 15 Jul 2020 12:08:14 +0000 (14:08 +0200)
When a stream is detached from a backend private connection, we must not insert
it in the available connection list. In addition, we must be sure to remove it
from this list. To ensure it is properly performed, this part has been slightly
refactored to clearly split processing of private connections from the others.

This patch should probably be backported to 2.2.

src/mux_fcgi.c

index a0509e66a6a4c1ccfb409b9a7fff28e942b9d014..76e93e4344d8d19708ad96c1c19ca4940a331f08 100644 (file)
@@ -3543,26 +3543,33 @@ static void fcgi_detach(struct conn_stream *cs)
                /* Never ever allow to reuse a connection from a non-reuse backend */
                if ((fconn->proxy->options & PR_O_REUSE_MASK) == PR_O_REUSE_NEVR)
                        fconn->conn->flags |= CO_FL_PRIVATE;
-               if (!fconn->conn->owner && (fconn->conn->flags & CO_FL_PRIVATE)) {
-                       fconn->conn->owner = sess;
-                       if (!session_add_conn(sess, fconn->conn, fconn->conn->target)) {
-                               fconn->conn->owner = NULL;
-                               if (eb_is_empty(&fconn->streams_by_id)) {
-                                       /* let's kill the connection right away */
-                                       fconn->conn->mux->destroy(fconn);
+               if (fconn->conn->flags & CO_FL_PRIVATE) {
+                       if (!fconn->conn->owner) {
+                               fconn->conn->owner = sess;
+                               if (!session_add_conn(sess, fconn->conn, fconn->conn->target)) {
+                                       fconn->conn->owner = NULL;
+                                       if (eb_is_empty(&fconn->streams_by_id)) {
+                                               /* let's kill the connection right away */
+                                               fconn->conn->mux->destroy(fconn);
+                                               TRACE_DEVEL("outgoing connection killed", FCGI_EV_STRM_END|FCGI_EV_FCONN_ERR);
+                                               return;
+                                       }
+                               }
+                       }
+                       if (eb_is_empty(&fconn->streams_by_id) && fconn->conn->owner == sess) {
+                               if (session_check_idle_conn(fconn->conn->owner, fconn->conn) != 0) {
+                                       /* The connection is destroyed, let's leave */
                                        TRACE_DEVEL("outgoing connection killed", FCGI_EV_STRM_END|FCGI_EV_FCONN_ERR);
                                        return;
                                }
                        }
+
+                       /* Be sure to remove the connection from the available_conns list */
+                       if (!MT_LIST_ISEMPTY(&fconn->conn->list))
+                               MT_LIST_DEL(&fconn->conn->list);
                }
-               if (eb_is_empty(&fconn->streams_by_id)) {
-                       if (sess && fconn->conn->owner == sess &&
-                           session_check_idle_conn(fconn->conn->owner, fconn->conn) != 0) {
-                               /* The connection is destroyed, let's leave */
-                               TRACE_DEVEL("outgoing connection killed", FCGI_EV_STRM_END|FCGI_EV_FCONN_ERR);
-                               return;
-                       }
-                       if (!(fconn->conn->flags & CO_FL_PRIVATE)) {
+               else {
+                       if (eb_is_empty(&fconn->streams_by_id)) {
                                if (!srv_add_to_idle_list(objt_server(fconn->conn->target), fconn->conn, 1)) {
                                        /* The server doesn't want it, let's kill the connection right away */
                                        fconn->conn->mux->destroy(fconn);
@@ -3576,11 +3583,11 @@ static void fcgi_detach(struct conn_stream *cs)
                                TRACE_DEVEL("reusable idle connection", FCGI_EV_STRM_END, fconn->conn);
                                return;
                        }
-               } else if (MT_LIST_ISEMPTY(&fconn->conn->list) &&
-                          fcgi_avail_streams(fconn->conn) > 0 && objt_server(fconn->conn->target)) {
+                       else if (MT_LIST_ISEMPTY(&fconn->conn->list) &&
+                                fcgi_avail_streams(fconn->conn) > 0 && objt_server(fconn->conn->target)) {
                                LIST_ADD(&__objt_server(fconn->conn->target)->available_conns[tid], mt_list_to_list(&fconn->conn->list));
                        }
-
+               }
        }
 
        /* We don't want to close right now unless we're removing the last