Fix data races in end-to-end tests

I discovered that I can reliably reproduce data races in two end-to-end tests by repeating the tests 100 times with TSan enabled. Like so:

```
blaze test --config=tsan --runs_per_test=100 //third_party/quic/core/http:end_to_end_test
```

The fix I came up with is to pause the server before calling `GetServerConnection()` and `GetServerSession()`. Both of these functions call, or transitively call, `GetDispatcher()`, which requires that `server_thread_` is paused.

Perhaps we can leverage thread safety annotations to make the compiler check this in the future.

PiperOrigin-RevId: 772980453
diff --git a/quiche/quic/core/http/end_to_end_test.cc b/quiche/quic/core/http/end_to_end_test.cc
index 6ae847b..090ef6d 100644
--- a/quiche/quic/core/http/end_to_end_test.cc
+++ b/quiche/quic/core/http/end_to_end_test.cc
@@ -444,6 +444,7 @@
     return client_session->connection();
   }
 
+  // Must be called while `server_thread_` is paused.
   QuicConnection* GetServerConnection() {
     QuicSpdySession* server_session = GetServerSession();
     if (server_session == nullptr) {
@@ -453,6 +454,7 @@
     return server_session->connection();
   }
 
+  // Must be called while `server_thread_` is paused.
   QuicSpdySession* GetServerSession() {
     QuicDispatcher* dispatcher = GetDispatcher();
     if (dispatcher == nullptr) {
@@ -468,7 +470,7 @@
         QuicDispatcherPeer::GetFirstSessionIfAny(dispatcher));
   }
 
-  // Must be called while server_thread_ is paused.
+  // Must be called while `server_thread_` is paused.
   QuicDispatcher* GetDispatcher() {
     if (!server_thread_) {
       ADD_FAILURE() << "Missing server thread";
@@ -482,7 +484,7 @@
     return QuicServerPeer::GetDispatcher(quic_server);
   }
 
-  // Must be called while server_thread_ is paused.
+  // Must be called while `server_thread_` is paused.
   const QuicDispatcherStats& GetDispatcherStats() {
     return GetDispatcher()->stats();
   }
@@ -7287,7 +7289,9 @@
 
   SendSynchronousFooRequestAndCheckResponse();
 
+  server_thread_->Pause();
   QuicSpdySession* server_session = GetServerSession();
+  server_thread_->Resume();
   EXPECT_FALSE(GetClientSession()->ShouldBufferRequestsUntilSettings());
   server_thread_->ScheduleAndWaitForCompletion([server_session] {
     EXPECT_TRUE(server_session->ShouldBufferRequestsUntilSettings());
@@ -8191,25 +8195,27 @@
   // Wait for handshake to complete, so that we can manipulate the server
   // connection without race conditions.
   server_thread_->WaitForCryptoHandshakeConfirmed();
+  server_thread_->Pause();
   QuicConnection* server_connection = GetServerConnection();
   QuicConnectionPeer::DisableEcnCodepointValidation(server_connection);
   QuicEcnCounts* ecn = QuicSentPacketManagerPeer::GetPeerEcnCounts(
       QuicConnectionPeer::GetSentPacketManager(server_connection),
       APPLICATION_DATA);
   EXPECT_TRUE(server_connection->set_ecn_codepoint(ECN_ECT1));
+  server_thread_->Resume();
   client_->SendSynchronousRequest("/foo");
   // A second request provides a packet for the client ACKs to go with.
   client_->SendSynchronousRequest("/foo");
-  server_thread_->Pause();
-  EXPECT_EQ(ecn->ect0, 0);
-  EXPECT_EQ(ecn->ce, 0);
-  if (!VersionHasIetfQuicFrames(version_.transport_version)) {
-    EXPECT_EQ(ecn->ect1, 0);
-  } else {
-    EXPECT_GT(ecn->ect1, 0);
-  }
-  server_connection->set_per_packet_options(nullptr);
-  server_thread_->Resume();
+
+  server_thread_->ScheduleAndWaitForCompletion([&] {
+    EXPECT_EQ(ecn->ce, 0);
+    if (!VersionHasIetfQuicFrames(version_.transport_version)) {
+      EXPECT_EQ(ecn->ect1, 0);
+    } else {
+      EXPECT_GT(ecn->ect1, 0);
+    }
+  });
+
   client_->Disconnect();
 }