BUG/MEDIUM: h2: Don't attempt to recv from h2_process_demux if we subscribed.

Modify h2c_restart_reading() to add a new parameter, to let it know if it
should consider if the buffer isn't empty when retrying to read or not, and
call h2c_restart_reading() using 0 as a parameter from h2_process_demux().
If we're leaving h2_process_demux() with a non-empty buffer, it means the
frame is incomplete, and we're waiting for more data, and if we already
subscribed, we'll be waken when more data are available.
Failing to do so means we'll be waken up in a loop until more data are
available.

This should be backported to 1.9.
This commit is contained in:
Olivier Houchard 2019-04-05 15:34:34 +02:00 committed by Olivier Houchard
parent 9ef2ad7844
commit 3ca18bf0bd

View File

@ -332,11 +332,12 @@ static inline int h2_recv_allowed(const struct h2c *h2c)
}
/* restarts reading on the connection if it was not enabled */
static inline void h2c_restart_reading(const struct h2c *h2c)
static inline void h2c_restart_reading(const struct h2c *h2c, int consider_buffer)
{
if (!h2_recv_allowed(h2c))
return;
if (!b_data(&h2c->dbuf) && (h2c->wait_event.events & SUB_RETRY_RECV))
if ((!consider_buffer || !b_data(&h2c->dbuf))
&& (h2c->wait_event.events & SUB_RETRY_RECV))
return;
tasklet_wakeup(h2c->wait_event.task);
}
@ -360,7 +361,7 @@ static int h2_buf_available(void *target)
if ((h2c->flags & H2_CF_DEM_DALLOC) && b_alloc_margin(&h2c->dbuf, 0)) {
h2c->flags &= ~H2_CF_DEM_DALLOC;
h2c_restart_reading(h2c);
h2c_restart_reading(h2c, 1);
return 1;
}
@ -369,7 +370,7 @@ static int h2_buf_available(void *target)
if (h2c->flags & H2_CF_DEM_MROOM) {
h2c->flags &= ~H2_CF_DEM_MROOM;
h2c_restart_reading(h2c);
h2c_restart_reading(h2c, 1);
}
return 1;
}
@ -378,7 +379,7 @@ static int h2_buf_available(void *target)
(h2s = h2c_st_by_id(h2c, h2c->dsi)) && h2s->cs &&
b_alloc_margin(&h2s->rxbuf, 0)) {
h2c->flags &= ~H2_CF_DEM_SALLOC;
h2c_restart_reading(h2c);
h2c_restart_reading(h2c, 1);
return 1;
}
@ -567,7 +568,7 @@ static int h2_init(struct connection *conn, struct proxy *prx, struct session *s
conn->ctx = h2c;
/* prepare to read something */
h2c_restart_reading(h2c);
h2c_restart_reading(h2c, 1);
return 0;
fail_stream:
hpack_dht_free(h2c->ddht);
@ -2529,7 +2530,7 @@ static void h2_process_demux(struct h2c *h2c)
h2s_notify_recv(h2s);
}
h2c_restart_reading(h2c);
h2c_restart_reading(h2c, 0);
}
/* process Tx frames from streams to be multiplexed. Returns > 0 if it reached
@ -3011,7 +3012,7 @@ static void h2_detach(struct conn_stream *cs)
!h2_frt_has_too_many_cs(h2c)) {
/* frontend connection was blocking new streams creation */
h2c->flags &= ~H2_CF_DEM_TOOMANY;
h2c_restart_reading(h2c);
h2c_restart_reading(h2c, 1);
}
/* this stream may be blocked waiting for some data to leave (possibly
@ -3029,7 +3030,7 @@ static void h2_detach(struct conn_stream *cs)
*/
h2c->flags &= ~H2_CF_DEM_BLOCK_ANY;
h2c->flags &= ~H2_CF_MUX_BLOCK_ANY;
h2c_restart_reading(h2c);
h2c_restart_reading(h2c, 1);
}
h2s_destroy(h2s);
@ -5258,7 +5259,7 @@ static size_t h2_rcv_buf(struct conn_stream *cs, struct buffer *buf, size_t coun
if (ret && h2c->dsi == h2s->id) {
/* demux is blocking on this stream's buffer */
h2c->flags &= ~H2_CF_DEM_SFULL;
h2c_restart_reading(h2c);
h2c_restart_reading(h2c, 1);
}
return ret;