BUG/MEDIUM: mux-h2: fix early close with option abortonclose

Olivier found that commit 99ad1b3e8 ("MINOR: mux-h2: stop relying on
CS_FL_REOS") managed to break abortonclose again with H2. What happens
is that while the CS_FL_REOS flag was set on some transitions to the
HREM state, it's not set on all and is in fact only set when the low
level connection is closed. So making the replacement condition match
the HREM and ERROR states is not correct and causes completely correct
requests to send advertise an early close of the connection layer while
only the stream's input is closed.

In order to avoid this, we now properly split the checks for the CLOSED
state and for the closed connection. This way there is no risk to set
the EOS flag too early on the connection.

No backport is needed.
This commit is contained in:
Willy Tarreau 2019-06-15 09:55:50 +02:00
parent bd20a9dd4e
commit 76c83826db

View File

@ -157,7 +157,6 @@ enum h2_ss {
#define H2_SS_HLOC_BIT (1UL << H2_SS_HLOC)
#define H2_SS_ERROR_BIT (1UL << H2_SS_ERROR)
#define H2_SS_CLOSED_BIT (1UL << H2_SS_CLOSED)
#define H2_SS_EOS_BITS (H2_SS_CLOSED_BIT|H2_SS_ERROR_BIT|H2_SS_HREM_BIT)
/* HTTP/2 stream flags (32 bit), in h2s->flags */
#define H2_SF_NONE 0x00000000
@ -2376,7 +2375,8 @@ static void h2_process_demux(struct h2c *h2c)
if (tmp_h2s != h2s && h2s && h2s->cs &&
(b_data(&h2s->rxbuf) ||
(H2_SS_MASK(h2s->st) & H2_SS_EOS_BITS) ||
conn_xprt_read0_pending(h2c->conn) ||
h2s->st == H2_SS_CLOSED ||
(h2s->flags & H2_SF_ES_RCVD) ||
(h2s->cs->flags & (CS_FL_ERROR|CS_FL_ERR_PENDING|CS_FL_EOS)))) {
/* we may have to signal the upper layers */
@ -2615,7 +2615,8 @@ static void h2_process_demux(struct h2c *h2c)
/* we can go here on missing data, blocked response or error */
if (h2s && h2s->cs &&
(b_data(&h2s->rxbuf) ||
(H2_SS_MASK(h2s->st) & H2_SS_EOS_BITS) ||
conn_xprt_read0_pending(h2c->conn) ||
h2s->st == H2_SS_CLOSED ||
(h2s->flags & H2_SF_ES_RCVD) ||
(h2s->cs->flags & (CS_FL_ERROR|CS_FL_ERR_PENDING|CS_FL_EOS)))) {
/* we may have to signal the upper layers */
@ -5411,7 +5412,7 @@ static size_t h2_rcv_buf(struct conn_stream *cs, struct buffer *buf, size_t coun
cs->flags &= ~(CS_FL_RCV_MORE | CS_FL_WANT_ROOM);
if (h2s->flags & H2_SF_ES_RCVD)
cs->flags |= CS_FL_EOI;
if (H2_SS_MASK(h2s->st) & H2_SS_EOS_BITS)
if (conn_xprt_read0_pending(h2c->conn) || h2s->st == H2_SS_CLOSED)
cs->flags |= CS_FL_EOS;
if (cs->flags & CS_FL_ERR_PENDING)
cs->flags |= CS_FL_ERROR;