]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mux-h2: do not emit GOAWAY on idle ping expiration
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 17 Apr 2025 09:14:10 +0000 (11:14 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 17 Apr 2025 12:49:36 +0000 (14:49 +0200)
If idle-ping is activated and h2c task is expired due to missing PING
ACK, consider that the peer is away and the connection can be closed
immediately. GOAWAY emission is thus skipped.

A new test is necessary in h2c_update_timeout() when PING ACK is
currently expected, but the next timer expiration selected is not
idle-ping. This may happen if http-keep-alive/http-request timers are
selected first. In this case, H2_CF_IDL_PING_SENT flag is resetted. This
is necessary to not prevent GOAWAY emission on expiration.

src/mux_h2.c

index 86e39e5e2373b8d437f15b223a9fd4d5448036b9..697918158d621312207b282b1d8b16e509b91698 100644 (file)
@@ -914,10 +914,18 @@ static void h2c_update_timeout(struct h2c *h2c)
                                        ping = tick_add_ifset(now_ms, conn_idle_ping(h2c->conn));
 
                                exp = tick_first(exp, ping);
-                               /* If PING timer selected, set flag to trigger its emission rather than conn deletion on next timeout. */
-                               if (tick_isset(exp) && exp == ping && ping != dft &&
-                                   !(h2c->flags & H2_CF_IDL_PING_SENT)) {
-                                       h2c->flags |= H2_CF_IDL_PING;
+
+                               if (tick_isset(exp)) {
+                                       if (exp == ping && ping != dft) {
+                                               /* PING timer selected, set flag to prevent conn deletion on next timeout. */
+                                               if (!(h2c->flags & H2_CF_IDL_PING_SENT))
+                                                       h2c->flags |= H2_CF_IDL_PING;
+                                       }
+                                       else if (h2c->flags & H2_CF_IDL_PING_SENT) {
+                                               /* timer other than ping selected, remove ping flag to allow GOAWAY on expiration. */
+                                               h2c->flags &= ~H2_CF_IDL_PING_SENT;
+                                               ABORT_NOW();
+                                       }
                                }
                        }
 
@@ -5220,6 +5228,12 @@ struct task *h2_timeout_task(struct task *t, void *context, unsigned int state)
 
                HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
 
+               if (h2c->flags & H2_CF_IDL_PING_SENT) {
+                       TRACE_STATE("expired on idle ping", H2_EV_H2C_WAKE, h2c->conn);
+                       /* Do not emit GOAWAY on idle ping expiration. */
+                       goto do_leave;
+               }
+
                /* Try to gracefully close idle connections by sending a GOAWAY first,
                 * and then waiting for the fin timeout.
                 */