mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-15 18:17:01 +00:00
BUG/MAJOR: mux-h2: Don't try to send data if we know it is no longer possible
In h2_send(), if we are in a state where we know it is no longer possible to send data, we must exit the sending loop to avoid any possiblity to loop forever. It may happen if the mbuf ring is released while the H2_CF_MUX_MFULL flag is still set. Here is a possible scenario to trigger the bug : 1) The mbuf ring is full because we are unable to send data. The H2_CF_MUX_MFULL flag is set on the H2 connection. 2) At this stage, the task timeout expires because the H2 connection is blocked. We enter in h2_timeout_task() function. Because the mbuf ring is full, we cannot send the GOAWAY frame. Thus the H2_CF_GOAWAY_FAILED flag is set. The H2 connection is not released yet because there is still a stream attached. Here we leave h2_timeout_task() function. 3) A bit later, the H2 connection is woken up. If h2_process(), nothing is performed by the first attempt to send data, in h2_send(). Then, because the H2_CF_GOAWAY_FAILED flag is set, the mbuf ring is released. But the H2_CF_MUX_MFULL flag is still there. At this step a second attempt to send data is performed. 4) In h2_send(), we try to send data in a loop. To exist this loop, done variable must be set to 1. Because the H2_CF_MUX_MFULL flag is set, we don't call h2_process_mux() and done is not updated. Because the mbuf ring is now empty, nothing is sent and the H2_CF_MUX_MFULL flag is never removed. Now, we loop forever... waiting for the watchdog. To fix the bug, we now exit the loop if one of these conditions is true : - The H2_CF_GOAWAY_FAILED flag is set on the H2 connection - The CO_FL_SOCK_WR_SH flag is set on the underlying connection - The H2 connection is in the H2_CS_ERROR2 state This patch should fix the issue #912 and most probably #875. It must be backported as far as the 1.8.
This commit is contained in:
parent
d6c48366b8
commit
9a3d3fcb5d
@ -3469,7 +3469,8 @@ static int h2_send(struct h2c *h2c)
|
||||
if (h2c->flags & H2_CF_MUX_MALLOC)
|
||||
done = 1; // we won't go further without extra buffers
|
||||
|
||||
if (conn->flags & CO_FL_ERROR)
|
||||
if ((conn->flags & (CO_FL_SOCK_WR_SH|CO_FL_ERROR)) ||
|
||||
(h2c->st0 == H2_CS_ERROR2) || (h2c->flags & H2_CF_GOAWAY_FAILED))
|
||||
break;
|
||||
|
||||
if (h2c->flags & (H2_CF_MUX_MFULL | H2_CF_DEM_MBUSY | H2_CF_DEM_MROOM))
|
||||
|
Loading…
Reference in New Issue
Block a user