From 67acfa74cd5cd4932418601769f44871883736f7 Mon Sep 17 00:00:00 2001 From: Radek Zikmund Date: Fri, 16 Oct 2026 13:21:57 +0200 Subject: [PATCH] Serialize HTTP/2 loopback writes and join reader before disposal Enable existing connection-scoped I/O serialization for stream-limit and keepalive tests. Dispose keepalive connections after joining frame processing so EOF cleanup cannot race final response writes. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3326d75e-588a-4534-9778-75e5812d65c0 --- .../tests/FunctionalTests/HttpClientHandlerTest.Http2.cs | 2 +- .../SocketsHttpHandlerTest.Http2KeepAlivePing.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http2.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http2.cs index 5af36835659fe6..c9b2eb1538ec63 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http2.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http2.cs @@ -1973,7 +1973,7 @@ public async Task Http2_SendOverConnectionWindowSizeWithoutExplicitFlush_ClientS [ConditionalFact(typeof(HttpClientHandlerTest_Http2), nameof(SupportsAlpn))] public async Task Http2_MaxConcurrentStreams_LimitEnforced() { - using (Http2LoopbackServer server = Http2LoopbackServer.CreateServer()) + using (Http2LoopbackServer server = Http2LoopbackServer.CreateServer(new Http2Options { EnsureThreadSafeIO = true })) using (HttpClient client = CreateHttpClient()) { Task sendTask = client.GetAsync(server.Address); diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Http2KeepAlivePing.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Http2KeepAlivePing.cs index b9bc85cfb45065..933dc42c6481c7 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Http2KeepAlivePing.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Http2KeepAlivePing.cs @@ -32,7 +32,7 @@ public sealed class SocketsHttpHandler_Http2KeepAlivePing_Test : HttpClientHandl private TaskCompletionSource _serverFinished = new TaskCompletionSource(); private bool _sendPingResponse = true; - private static Http2Options NoAutoPingResponseHttp2Options => new Http2Options() { EnableTransparentPingResponse = false }; + private static Http2Options NoAutoPingResponseHttp2Options => new Http2Options() { EnableTransparentPingResponse = false, EnsureThreadSafeIO = true }; private static readonly TimeSpan TestTimeout = TimeSpan.FromSeconds(60); @@ -92,7 +92,7 @@ await Http2LoopbackServer.CreateClientAndServerAsync(async uri => Assert.True(_pingCounter <= 1); await TerminateLoopbackConnectionAsync(); - }); + }, new Http2Options { EnsureThreadSafeIO = true }); } [OuterLoop("Runs long")] @@ -566,7 +566,6 @@ private async Task ProcessIncomingFramesAsync(CancellationToken cancellationToke } _output?.WriteLine("ProcessIncomingFramesAsync finished"); - await _connection.DisposeAsync(); } private async Task EstablishConnectionAsync(Http2LoopbackServer server, params SettingsEntry[] settingsEntries) @@ -580,6 +579,7 @@ private async Task TerminateLoopbackConnectionAsync() _serverFinished.SetResult(); _incomingFramesCts.Cancel(); await _incomingFramesTask; + await _connection.DisposeAsync(); } private async Task GuardConnectionWriteAsync(Func action, CancellationToken cancellationToken = default)