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.
This commit is contained in:
Willy Tarreau 2019-05-14 10:44:40 +02:00
parent aebbe5ef72
commit 3cf69fe6b2

View File

@ -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);
}