Skip to content

Commit

Permalink
BUG/MINOR: quic: prevent freeze after early QCS closure
Browse files Browse the repository at this point in the history
A connection freeze may occur if a QCS is released before transmitting
any data. This can happen when an error is detected early by the stream,
for example during HTTP response headers encoding, forcing the whole
connection closure.

In this case, a connection error is registered by the QUIC MUX to the
lower layer. MUX is then release and xprt layer is notified to prepare
CONNECTION_CLOSE emission. However, this is prevented because quic_conn
streams tree is not empty as it contains the qc_stream_desc previously
attached to the failed QCS instance. The connection will freeze until
QUIC idle timeout.

This situation is caused by an omission during qc_stream_desc release
operation. In the described situation, qc_stream_desc current buffer is
empty and can thus by removed, which is the purpose of this patch. This
unblocks this previously failed situation, with qc_stream_desc removal
from quic_conn tree.

This issue can be reproduced by modifying H3/QPACK code to return an
early error during HEADERS response processing.

This must be backported up to 2.6, after a period of observation.

(cherry picked from commit 3ef1ee4)
Signed-off-by: Christopher Faulet <[email protected]>
  • Loading branch information
a-denoyelle authored and capflam committed Sep 19, 2024
1 parent 0f7ae82 commit 3eaa586
Showing 1 changed file with 4 additions and 5 deletions.
9 changes: 4 additions & 5 deletions src/quic_stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,11 @@ void qc_stream_desc_release(struct qc_stream_desc *stream,
BUG_ON(final_size > tail_offset);

/* Remove unsent data from current buffer. */
if (final_size < tail_offset) {
if (final_size < tail_offset)
b_sub(buf, tail_offset - final_size);
/* Remove buffer if all ACK already received. */
if (!b_data(buf))
qc_stream_buf_free(stream, &stream_buf);
}

if (!b_data(buf))
qc_stream_buf_free(stream, &stream_buf);

/* A released stream does not use <stream.buf>. */
stream->buf = NULL;
Expand Down

0 comments on commit 3eaa586

Please sign in to comment.