]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: mux-h2: prevent past scheduling with idle connections
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 9 Apr 2025 12:26:54 +0000 (14:26 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 17 Apr 2025 12:49:36 +0000 (14:49 +0200)
While reviewing HTTP/2 MUX timeout, it seems there is a possibility that
MUX task is requeued via h2c_update_timeout() with an already expired
date. This can happens with idle connections on two cases :
* first with shut timeout, as timer is not refreshed if already set
* second with http-request and keep-alive timers, which are based on
  idle_start

Queuing an already expired task is an undefined behavior. Fix this by
using task_wakeup() instead of task_queue() at the end of
h2c_update_timeout() if such case occurs.

This should be backported up to 2.6.

src/mux_h2.c

index 9daa6e7d260f8bba24e332fe82c2b3040cc3978c..c0dc7c393842081e53807ebbe3444fd094757007 100644 (file)
@@ -921,6 +921,16 @@ static void h2c_update_timeout(struct h2c *h2c)
        } else {
                h2c->task->expire = TICK_ETERNITY;
        }
+
+       /* Timer may already be expired, in this case it must not be requeued.
+        * Currently it may happen with idle conn calculation based on shut or
+        * http-req/ka timeouts.
+        */
+       if (unlikely(tick_is_expired(h2c->task->expire, now_ms))) {
+               task_wakeup(h2c->task, TASK_WOKEN_TIMER);
+               goto leave;
+       }
+
        task_queue(h2c->task);
  leave:
        TRACE_LEAVE(H2_EV_H2C_WAKE);