]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mux-h1: rework the h1_timeout_task() function
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 29 Sep 2020 13:30:15 +0000 (15:30 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 4 Dec 2020 13:41:48 +0000 (14:41 +0100)
Mainly to make it easier to read. First of all, when a H1 connection is
still there, we check if the connection was stolen by another thread or
not. If yes we release the task and leave. Then we check if the task is
expired or not. Only expired tasks are considered. Finally, if a conn-stream
is still attached to the connection (H1C_F_CS_ATTACHED flag set), we
return. Otherwise, the task and the H1 connection are released.

src/mux_h1.c

index 1be50f509086f2b4b8ebe02bed5423d455c87be6..467c7c730e55e175bab6673197ca019966ca1684 100644 (file)
@@ -2319,30 +2319,47 @@ static struct task *h1_timeout_task(struct task *t, void *context, unsigned shor
        struct h1c *h1c = context;
        int expired = tick_is_expired(t->expire, now_ms);
 
-       TRACE_POINT(H1_EV_H1C_WAKE, h1c ? h1c->conn : NULL);
+       TRACE_ENTER(H1_EV_H1C_WAKE, h1c ? h1c->conn : NULL);
 
        if (h1c) {
+                /* Make sure nobody stole the connection from us */
+               HA_SPIN_LOCK(OTHER_LOCK, &idle_conns[tid].takeover_lock);
+
+               /* Somebody already stole the connection from us, so we should not
+                * free it, we just have to free the task.
+                */
+               if (!t->context) {
+                       h1c = NULL;
+                       HA_SPIN_UNLOCK(OTHER_LOCK, &idle_conns[tid].takeover_lock);
+                       goto do_leave;
+               }
+
                if (!expired) {
-                       TRACE_DEVEL("leaving (not expired)", H1_EV_H1C_WAKE, h1c->conn);
+                       HA_SPIN_UNLOCK(OTHER_LOCK, &idle_conns[tid].takeover_lock);
+                       TRACE_DEVEL("leaving (not expired)", H1_EV_H1C_WAKE, h1c->conn, h1c->h1s);
                        return t;
                }
 
-               /* We're about to destroy the connection, so make sure nobody attempts
-                * to steal it from us.
+               /* If a conn-stream is still attached to the mux, wait for the
+                * stream's timeout
                 */
-               HA_SPIN_LOCK(OTHER_LOCK, &idle_conns[tid].takeover_lock);
+               if (h1c->flags & H1C_F_CS_ATTACHED) {
+                       HA_SPIN_UNLOCK(OTHER_LOCK, &idle_conns[tid].takeover_lock);
+                       t->expire = TICK_ETERNITY;
+                       TRACE_DEVEL("leaving (CS still attached)", H1_EV_H1C_WAKE, h1c->conn, h1c->h1s);
+                       return t;
+               }
 
-               /* Somebody already stole the connection from us, so we should not
-                * free it, we just have to free the task.
+               /* We're about to destroy the connection, so make sure nobody attempts
+                * to steal it from us.
                 */
-               if (!t->context)
-                       h1c = NULL;
-               else if (h1c->conn->flags & CO_FL_LIST_MASK)
+               if (h1c->conn->flags & CO_FL_LIST_MASK)
                        MT_LIST_DEL(&h1c->conn->list);
 
                HA_SPIN_UNLOCK(OTHER_LOCK, &idle_conns[tid].takeover_lock);
        }
 
+  do_leave:
        task_destroy(t);
 
        if (!h1c) {
@@ -2352,17 +2369,8 @@ static struct task *h1_timeout_task(struct task *t, void *context, unsigned shor
        }
 
        h1c->task = NULL;
-       /* If a stream is still attached to the mux, just set an error and wait
-        * for the stream's timeout. Otherwise, release the mux. This is only ok
-        * because same timeouts are used.
-        */
-       if (h1c->flags & H1C_F_CS_ATTACHED) {
-               h1c->flags |= H1C_F_CS_ERROR;
-               TRACE_STATE("error on h1c, h1s still attached (expired)", H1_EV_H1C_WAKE|H1_EV_H1C_ERR, h1c->conn, h1c->h1s);
-       }
-       else
-               h1_release(h1c);
-
+       h1_release(h1c);
+       TRACE_LEAVE(H1_EV_H1C_WAKE);
        return NULL;
 }