Skip to content

Commit

Permalink
BUG/MEDIUM: mux-h2: Set ES flag when necessary on 0-copy data forwarding
Browse files Browse the repository at this point in the history
When DATA frames are sent via the 0-copy data forwarding, we must take care
to set the ES flag on the last DATA frame. It should be performed in
h2_done_ff() when IOBUF_FL_EOI flag was set by the producer. This flag is
here to know when the producer has reached the end of input. When this
happens, the h2s state is also updated. It is switched to "half-closed
local" or "closed" state depending on its previous state.

It is mainly an issue on uploads because the server may be blocked waiting
for the end of the request. A workaround is to disable the 0-copy forwarding
support the the H2 by setting "tune.h2.zero-copy-fwd-send" directive to off
in your global section.

This patch should fix the issue #2665. It must be backported as far as 2.9.
  • Loading branch information
capflam committed Aug 28, 2024
1 parent 0d142e0 commit 4ef5251
Showing 1 changed file with 16 additions and 1 deletion.
17 changes: 16 additions & 1 deletion src/mux_h2.c
Original file line number Diff line number Diff line change
Expand Up @@ -7372,6 +7372,7 @@ static size_t h2_done_ff(struct stconn *sc)
struct buffer *mbuf;
char *head;
size_t total = 0;
int es_now = 0;

TRACE_ENTER(H2_EV_H2S_SEND|H2_EV_STRM_SEND, h2s->h2c->conn, h2s);

Expand All @@ -7380,8 +7381,10 @@ static size_t h2_done_ff(struct stconn *sc)
goto end;
head = b_peek(mbuf, b_data(mbuf) - sd->iobuf.data);

if (sd->iobuf.flags & IOBUF_FL_EOI)
if (sd->iobuf.flags & IOBUF_FL_EOI) {
es_now = 1;
h2s->flags &= ~H2_SF_MORE_HTX_DATA;
}

if (!(sd->iobuf.flags & IOBUF_FL_FF_BLOCKED) &&
!(h2s->flags & H2_SF_BLK_SFCTL) &&
Expand All @@ -7398,12 +7401,24 @@ static size_t h2_done_ff(struct stconn *sc)
*/
total = sd->iobuf.data;
h2_set_frame_size(head, total);
if (es_now)
head[4] |= H2_F_DATA_END_STREAM;
b_add(mbuf, 9);
h2s->sws -= total;
h2c->mws -= total;
if (h2_send(h2s->h2c))
tasklet_wakeup(h2s->h2c->wait_event.tasklet);

if (es_now) {
if (h2s->st == H2_SS_OPEN)
h2s->st = H2_SS_HLOC;
else
h2s_close(h2s);

h2s->flags |= H2_SF_ES_SENT;
TRACE_PROTO("ES flag set on outgoing frame", H2_EV_TX_FRAME|H2_EV_TX_DATA|H2_EV_TX_EOI, h2c->conn, h2s);
}

end:
sd->iobuf.buf = NULL;
sd->iobuf.offset = 0;
Expand Down

0 comments on commit 4ef5251

Please sign in to comment.