Correctly handle ignore_read_data case when sequencer gets unblocked. Notes: The divergence of code on ignore_read_data_ is a well exercised pattern (quic/core/quic_stream_sequencer.cc;l=126-130;bpv=1;bpt=0;rcl=834059230) in that data should not be passed up when application asks to ignore them. Protected by FLAGS_quic_reloadable_flag_quic_fix_ignore_read_data_when_unblocked. PiperOrigin-RevId: 885296351
diff --git a/quiche/common/quiche_feature_flags_list.h b/quiche/common/quiche_feature_flags_list.h index 8c58b90..709670c 100755 --- a/quiche/common/quiche_feature_flags_list.h +++ b/quiche/common/quiche_feature_flags_list.h
@@ -43,6 +43,7 @@ QUICHE_FLAG(bool, quiche_reloadable_flag_quic_enobufs_blocked, true, true, "If true, ENOBUFS socket errors are reported as socket blocked instead of socket failure.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_fin_before_completed_http_headers, false, true, "If true, close the connection with error if FIN is received before finish receiving the whole HTTP headers.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_fix_gap_filling_ack_logic, false, false, "If true, fix the gap filling ack logic in QuicAckFrame.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_fix_ignore_read_data_when_unblocked, false, false, "If true, correctly handle ignore_read_data case when sequencer gets unblocked.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_fix_timeouts, true, true, "If true, postpone setting handshake timeout to infinite to handshake complete.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_include_datagrams_in_willing_to_write, false, false, "If true, checks for queued datagrams when determining if a connection is willing to write.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_move_clock_now, false, false, "If true, move the call to clock.Now() in QuicPacketReader::ReadAndDispatchPackets to after socket_api_.ReadMultiplePackets().")
diff --git a/quiche/quic/core/http/quic_spdy_stream_test.cc b/quiche/quic/core/http/quic_spdy_stream_test.cc index 8acea52..3038037 100644 --- a/quiche/quic/core/http/quic_spdy_stream_test.cc +++ b/quiche/quic/core/http/quic_spdy_stream_test.cc
@@ -3860,15 +3860,15 @@ EXPECT_TRUE(stream_->sequencer()->HasBytesToRead()); EXPECT_TRUE(QuicSpdyStreamPeer::BodyManager(stream_).HasBytesToRead()); - // QUIC gets blocked. - stream_->sequencer()->SetBlockedUntilFlush(); - // In Envoy QUIC, StopReading can be called after local reset. stream_->StopReading(); // Sequencer is not closed but the bytes in body_manager is cleared. EXPECT_FALSE(stream_->sequencer()->IsClosed()); EXPECT_FALSE(QuicSpdyStreamPeer::BodyManager(stream_).HasBytesToRead()); + // QUIC gets blocked. + stream_->sequencer()->SetBlockedUntilFlush(); + // FIN does not close the read side since the stream is blocked. QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(0), /*fin=*/true, offset, "second body"); @@ -3888,7 +3888,11 @@ // QUIC gets unblocked. stream_->sequencer()->SetUnblocked(); - EXPECT_FALSE(stream_->read_side_closed()); + if (GetQuicReloadableFlag(quic_fix_ignore_read_data_when_unblocked)) { + EXPECT_TRUE(stream_->read_side_closed()); + } else { + EXPECT_FALSE(stream_->read_side_closed()); + } } } // namespace
diff --git a/quiche/quic/core/quic_stream_sequencer.cc b/quiche/quic/core/quic_stream_sequencer.cc index 13a1668..dcb6252 100644 --- a/quiche/quic/core/quic_stream_sequencer.cc +++ b/quiche/quic/core/quic_stream_sequencer.cc
@@ -24,6 +24,7 @@ #include "quiche/quic/platform/api/quic_flags.h" #include "quiche/quic/platform/api/quic_logging.h" #include "quiche/quic/platform/api/quic_stack_trace.h" +#include "quiche/common/platform/api/quiche_flag_utils.h" namespace quic { @@ -265,6 +266,16 @@ void QuicStreamSequencer::SetUnblocked() { blocked_ = false; + if (GetQuicReloadableFlag(quic_fix_ignore_read_data_when_unblocked)) { + QUICHE_RELOADABLE_FLAG_COUNT_N(quic_fix_ignore_read_data_when_unblocked, 1, + 2); + if (ignore_read_data_) { + QUICHE_RELOADABLE_FLAG_COUNT_N(quic_fix_ignore_read_data_when_unblocked, + 2, 2); + FlushBufferedFrames(); + return; + } + } if (IsClosed() || HasBytesToRead()) { stream_->OnDataAvailable(); }