Do not send RETIRE_CONNECTION_ID frame when the connection is closed.

There's recently another bug found at https://bugs.chromium.org/p/chromium/issues/detail?id=1514016 where multiple RETIRE_CONNECTION_ID frames are sent. If one of the send triggers connection close, the following send will encounter the QUIC_BUG.

Protected by quic_reloadable_flag_quic_no_write_control_frame_upon_connection_close2.

PiperOrigin-RevId: 599216282
diff --git a/quiche/quic/core/quic_flags_list.h b/quiche/quic/core/quic_flags_list.h
index bc0890b..bbf4aeb 100644
--- a/quiche/quic/core/quic_flags_list.h
+++ b/quiche/quic/core/quic_flags_list.h
@@ -41,6 +41,8 @@
 QUIC_FLAG(quic_reloadable_flag_quic_enable_mtu_discovery_at_server, false)
 // If true, QuicGsoBatchWriter will support release time if it is available and the process has the permission to do so.
 QUIC_FLAG(quic_restart_flag_quic_support_release_time_for_gso, false)
+// If true, QuicSession will block outgoing control frames when the connection is closed.
+QUIC_FLAG(quic_reloadable_flag_quic_no_write_control_frame_upon_connection_close2, false)
 // If true, ack frequency frame can be sent from server to client.
 QUIC_FLAG(quic_reloadable_flag_quic_can_send_ack_frequency, true)
 // If true, allow client to enable BBRv2 on server via connection option \'B2ON\'.
diff --git a/quiche/quic/core/quic_session.cc b/quiche/quic/core/quic_session.cc
index 665e4ff..6e655c5 100644
--- a/quiche/quic/core/quic_session.cc
+++ b/quiche/quic/core/quic_session.cc
@@ -2232,6 +2232,14 @@
 }
 
 void QuicSession::SendRetireConnectionId(uint64_t sequence_number) {
+  if (GetQuicReloadableFlag(
+          quic_no_write_control_frame_upon_connection_close2)) {
+    QUIC_RELOADABLE_FLAG_COUNT(
+        quic_no_write_control_frame_upon_connection_close2);
+    if (!connection_->connected()) {
+      return;
+    }
+  }
   control_frame_manager_.WriteOrBufferRetireConnectionId(sequence_number);
 }
 
diff --git a/quiche/quic/core/quic_session_test.cc b/quiche/quic/core/quic_session_test.cc
index 8950bc1..897cc80 100644
--- a/quiche/quic/core/quic_session_test.cc
+++ b/quiche/quic/core/quic_session_test.cc
@@ -2220,6 +2220,24 @@
       &session_, GetNthClientInitiatedBidirectionalId(1)));
 }
 
+// Regression test for
+// https://bugs.chromium.org/p/chromium/issues/detail?id=1514016
+TEST_P(QuicSessionTestClient, DonotSendRetireCIDFrameWhenConnectionClosed) {
+  if (!VersionHasIetfQuicFrames(transport_version())) {
+    return;
+  }
+  connection_->ReallyCloseConnection(QUIC_NO_ERROR, "closing",
+                                     ConnectionCloseBehavior::SILENT_CLOSE);
+  EXPECT_FALSE(connection_->connected());
+  if (!GetQuicReloadableFlag(
+          quic_no_write_control_frame_upon_connection_close2)) {
+    EXPECT_QUIC_BUG(session_.SendRetireConnectionId(20),
+                    "Try to write control frame");
+  } else {
+    session_.SendRetireConnectionId(20);
+  }
+}
+
 TEST_P(QuicSessionTestClient, NewStreamCreationResumesMultiPortProbing) {
   if (!VersionHasIetfQuicFrames(transport_version())) {
     return;