From: Willy Tarreau Date: Tue, 14 May 2019 08:44:40 +0000 (+0200) Subject: BUG/MINOR: mux-h2: make sure to honor KILL_CONN in do_shut{r,w} X-Git-Tag: v2.0-dev3~11 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3cf69fe6b2d591faa736c24ef87a46156ca07de5;p=thirdparty%2Fhaproxy.git BUG/MINOR: mux-h2: make sure to honor KILL_CONN in do_shut{r,w} If the stream closes and quits while there's no room in the mux buffer to send an RST frame, next time it is attempted it will not lead to the connection being closed because the conn_stream will have been released and the KILL_CONN flag with it as well. This patch reserves a new H2_SF_KILL_CONN flag that is copied from the CS when calling shut{r,w} so that the stream remains autonomous on this even when the conn_stream leaves. This should ideally be backported to 1.9 though it depends on several previous patches that may or may not be suitable for backporting. The severity is very low so there's no need to insist in case of trouble. --- diff --git a/src/mux_h2.c b/src/mux_h2.c index 8dcf27855b..bf6c53de45 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -180,6 +180,7 @@ enum h2_ss { #define H2_SF_WANT_SHUTR 0x00008000 // a stream couldn't shutr() (mux full/busy) #define H2_SF_WANT_SHUTW 0x00010000 // a stream couldn't shutw() (mux full/busy) +#define H2_SF_KILL_CONN 0x00020000 // kill the whole connection with this stream /* H2 stream descriptor, describing the stream as it appears in the H2C, and as @@ -3170,7 +3171,7 @@ static void h2_do_shutr(struct h2s *h2s) * normally used to limit abuse. In this case we schedule a goaway to * close the connection. */ - if ((h2s->cs && h2s->cs->flags & CS_FL_KILL_CONN) && + if ((h2s->flags & H2_SF_KILL_CONN) && !(h2c->flags & (H2_CF_GOAWAY_SENT|H2_CF_GOAWAY_FAILED))) { h2c_error(h2c, H2_ERR_ENHANCE_YOUR_CALM); h2s_error(h2s, H2_ERR_ENHANCE_YOUR_CALM); @@ -3236,7 +3237,7 @@ static void h2_do_shutw(struct h2s *h2s) * normally used to limit abuse. In this case we schedule a goaway to * close the connection. */ - if ((h2s->cs && h2s->cs->flags & CS_FL_KILL_CONN) && + if ((h2s->flags & H2_SF_KILL_CONN) && !(h2c->flags & (H2_CF_GOAWAY_SENT|H2_CF_GOAWAY_FAILED))) { h2c_error(h2c, H2_ERR_ENHANCE_YOUR_CALM); h2s_error(h2s, H2_ERR_ENHANCE_YOUR_CALM); @@ -3313,6 +3314,9 @@ static void h2_shutr(struct conn_stream *cs, enum cs_shr_mode mode) { struct h2s *h2s = cs->ctx; + if (cs->flags & CS_FL_KILL_CONN) + h2s->flags |= H2_SF_KILL_CONN; + if (!mode) return; @@ -3324,6 +3328,9 @@ static void h2_shutw(struct conn_stream *cs, enum cs_shw_mode mode) { struct h2s *h2s = cs->ctx; + if (cs->flags & CS_FL_KILL_CONN) + h2s->flags |= H2_SF_KILL_CONN; + h2_do_shutw(h2s); }