diff --git a/src/libraries/Common/tests/System/Net/Http/GenericLoopbackServer.cs b/src/libraries/Common/tests/System/Net/Http/GenericLoopbackServer.cs index f92e651ec0a675..1401642867d349 100644 --- a/src/libraries/Common/tests/System/Net/Http/GenericLoopbackServer.cs +++ b/src/libraries/Common/tests/System/Net/Http/GenericLoopbackServer.cs @@ -88,10 +88,11 @@ public void Dispose() _socket?.Dispose(); _websocket?.Dispose(); } - public void Close() + + public async Task CloseAsync() { _socket?.Close(); - CloseWebSocket(); + await CloseWebSocketAsync(); } public EndPoint? LocalEndPoint => _socket?.LocalEndPoint; @@ -108,13 +109,13 @@ public async Task WaitForCloseAsync(CancellationToken cancellationToken) } } - public void Shutdown(SocketShutdown how) + public async Task ShutdownAsync(SocketShutdown how) { _socket?.Shutdown(how); - CloseWebSocket(); + await CloseWebSocketAsync(); } - private void CloseWebSocket() + private async Task CloseWebSocketAsync() { if (_websocket == null) return; @@ -123,12 +124,11 @@ private void CloseWebSocket() try { - var task = _websocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "closing remoteLoop", CancellationToken.None); - // Block and wait for the task to complete synchronously - Task.WaitAll(task); + await _websocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "closing remoteLoop", CancellationToken.None); } catch (Exception) { + // Ignore exceptions during WebSocket close in test cleanup. } } } diff --git a/src/libraries/Common/tests/System/Net/Http/Http2LoopbackConnection.cs b/src/libraries/Common/tests/System/Net/Http/Http2LoopbackConnection.cs index 58bc1a8ccc5141..8b018da6d55b72 100644 --- a/src/libraries/Common/tests/System/Net/Http/Http2LoopbackConnection.cs +++ b/src/libraries/Common/tests/System/Net/Http/Http2LoopbackConnection.cs @@ -155,7 +155,7 @@ private async Task ReadPrefixAsync() // so that SocketsHttpHandler will not induce retry. // The contents of what we send don't really matter, as long as it is interpreted by SocketsHttpHandler as an invalid response. await _connectionStream.WriteAsync("HTTP/2.0 400 Bad Request\r\n\r\n"u8.ToArray()); - _connectionSocket.Shutdown(SocketShutdown.Send); + await _connectionSocket.ShutdownAsync(SocketShutdown.Send); // If WinHTTP doesn't support streaming a request without a length then it will fallback // to HTTP/1.1. Throwing an exception to detect this case in WinHttpHandler tests. throw new Exception("HTTP/1.1 request sent to HTTP/2 connection."); @@ -397,9 +397,12 @@ public async Task WaitForClientDisconnectAsync(bool ignoreUnexpectedFrames = fal _ignoreWindowUpdates = false; } - public void ShutdownSend() + public async Task ShutdownSendAsync() { - _connectionSocket?.Shutdown(SocketShutdown.Send); + if (_connectionSocket != null) + { + await _connectionSocket.ShutdownAsync(SocketShutdown.Send); + } } // This will cause a server-initiated shutdown of the connection. @@ -408,7 +411,7 @@ public void ShutdownSend() public async Task WaitForConnectionShutdownAsync(bool ignoreUnexpectedFrames = false) { // Shutdown our send side, so the client knows there won't be any more frames coming. - ShutdownSend(); + await ShutdownSendAsync(); await WaitForClientDisconnectAsync(ignoreUnexpectedFrames: ignoreUnexpectedFrames); } diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.AutoRedirect.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.AutoRedirect.cs index 8161d1a8198659..c45d954d92b97d 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.AutoRedirect.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.AutoRedirect.cs @@ -108,7 +108,7 @@ await LoopbackServer.CreateServerAsync(async (redirServer, redirUrl) => // Send Connection: close so the client will close connection after request is sent, // meaning we can just read to the end to get the content await connection.ReadRequestHeaderAndSendResponseAsync((HttpStatusCode)statusCode, $"Location: {redirUrl}\r\nConnection: close\r\n"); - connection.Socket.Shutdown(SocketShutdown.Send); + await connection.Socket.ShutdownAsync(SocketShutdown.Send); await connection.ReadToEndAsync(); }); @@ -124,7 +124,7 @@ await LoopbackServer.CreateServerAsync(async (redirServer, redirUrl) => // Send Connection: close so the client will close connection after request is sent, // meaning we can just read to the end to get the content receivedRequest = await connection.ReadRequestHeaderAndSendResponseAsync(additionalHeaders: "Connection: close\r\n"); - connection.Socket.Shutdown(SocketShutdown.Send); + await connection.Socket.ShutdownAsync(SocketShutdown.Send); receivedContent = await connection.ReadToEndAsync(); }); diff --git a/src/libraries/Common/tests/System/Net/Http/LoopbackServer.cs b/src/libraries/Common/tests/System/Net/Http/LoopbackServer.cs index 0ac084afc4e3e2..ac80fe227c4579 100644 --- a/src/libraries/Common/tests/System/Net/Http/LoopbackServer.cs +++ b/src/libraries/Common/tests/System/Net/Http/LoopbackServer.cs @@ -155,7 +155,10 @@ public async Task EstablishConnectionAsync() } catch (Exception) { - closableWrapper?.Close(); + if (closableWrapper is not null) + { + await closableWrapper.CloseAsync().ConfigureAwait(false); + } throw; } } @@ -679,7 +682,10 @@ public override async ValueTask DisposeAsync() // This seems to help avoid connection reset issues caused by buffered data // that has not been sent/acked when the graceful shutdown timeout expires. // This may throw if the socket was already closed, so eat any exception. - _socket?.Shutdown(SocketShutdown.Send); + if (_socket is not null) + { + await _socket.ShutdownAsync(SocketShutdown.Send).ConfigureAwait(false); + } } catch (Exception) { } 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 e96eb1fe25dc25..416cd342435a69 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http2.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http2.cs @@ -1077,7 +1077,7 @@ await Http2LoopbackServer.CreateClientAndServerAsync(async uri => // Server sends GOAWAY frame await connection.SendGoAway(streamId, ProtocolErrors.ENHANCE_YOUR_CALM); - connection.ShutdownSend(); + await connection.ShutdownSendAsync(); }); } @@ -1487,7 +1487,7 @@ public async Task GoAwayFrame_AllPendingStreamsValid_RequestsSucceedAndConnectio await connection.SendResponseDataAsync(streamId3, new byte[5], endStream: true); // We will not send any more frames, so send EOF now, and ensure the client handles this properly. - connection.ShutdownSend(); + await connection.ShutdownSendAsync(); // Receive all responses HttpResponseMessage response1 = await sendTask1; diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.RequestRetry.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.RequestRetry.cs index 8198fb8818a08e..f2ddaec419770b 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.RequestRetry.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.RequestRetry.cs @@ -142,7 +142,7 @@ await LoopbackServer.CreateClientAndServerAsync(async url => await server.AcceptConnectionAsync(async connection => { // Shut down the listen socket so no additional connections can happen - server.ListenSocket.Close(); + await server.ListenSocket.CloseAsync(); // Initial response await connection.ReadRequestHeaderAndSendResponseAsync(content: SimpleContent); diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ResponseDrain.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ResponseDrain.cs index 6c174266884e68..c28adb9dbe9f28 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ResponseDrain.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ResponseDrain.cs @@ -55,7 +55,7 @@ await LoopbackServer.CreateClientAndServerAsync( { await server.AcceptConnectionAsync(async connection => { - server.ListenSocket.Close(); // Shut down the listen socket so attempts at additional connections would fail on the client + await server.ListenSocket.CloseAsync(); // Shut down the listen socket so attempts at additional connections would fail on the client string response = LoopbackServer.GetContentModeResponse(mode, simpleContent); await connection.ReadRequestHeaderAndSendCustomResponseAsync(response); diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientMiniStressTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientMiniStressTest.cs index b739faf0dd72d8..e19c321dfd0a55 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientMiniStressTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientMiniStressTest.cs @@ -79,7 +79,7 @@ await server.AcceptConnectionAsync(async connection => Assert.Equal(numBytes, await connection.ReadBlockAsync(postData, 0, numBytes)); await connection.WriteStringAsync(responseText).ConfigureAwait(false); - connection.Socket.Shutdown(SocketShutdown.Send); + await connection.Socket.ShutdownAsync(SocketShutdown.Send); }); (await postAsync.ConfigureAwait(false)).Dispose(); diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/MetricsTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/MetricsTest.cs index bbe6c0bfbf9fb9..a70230c3ec9808 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/MetricsTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/MetricsTest.cs @@ -1116,7 +1116,7 @@ await LoopbackServer.CreateClientAndServerAsync(async uri => await IgnoreExceptions(async () => { LoopbackServer.Connection connection = await server.EstablishConnectionAsync().WaitAsync(cancelServerCts.Token); - connection.Socket.Shutdown(SocketShutdown.Send); + await connection.Socket.ShutdownAsync(SocketShutdown.Send); }); }); } diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs index d2f89a212f4ed0..b218cca0ee8dcb 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs @@ -592,7 +592,7 @@ await LoopbackServer.CreateClientAndServerAsync( string response = LoopbackServer.GetContentModeResponse(mode, content); await server.AcceptConnectionAsync(async connection => { - server.ListenSocket.Close(); // Shut down the listen socket so attempts at additional connections would fail on the client + await server.ListenSocket.CloseAsync(); // Shut down the listen socket so attempts at additional connections would fail on the client await connection.ReadRequestHeaderAndSendCustomResponseAsync(response); await connection.ReadRequestHeaderAndSendCustomResponseAsync(response); }); @@ -1941,7 +1941,7 @@ await server.AcceptConnectionAsync(async (LoopbackServer.Connection connection) string bigString = string.Concat(Enumerable.Repeat("abcdefghijklmnopqrstuvwxyz", 1000)); Task lotsOfDataSent = connection.SendResponseAsync(Encoding.ASCII.GetBytes(bigString)); - connection.Socket.Shutdown(SocketShutdown.Send); + await connection.Socket.ShutdownAsync(SocketShutdown.Send); await copyTask; await lotsOfDataSent; Assert.Equal("ghijklmnopqrstuvwxyz" + bigString, Encoding.ASCII.GetString(ms.ToArray())); @@ -2165,7 +2165,7 @@ await Http2LoopbackServerFactory.CreateServerAsync(async (server, url) => await request2; // Close underlying socket from first connection. - socket.Close(); + await socket.CloseAsync(); } }); } diff --git a/src/libraries/System.Net.WebSockets.Client/tests/LoopbackServer/WebSocketHandshakeHelper.cs b/src/libraries/System.Net.WebSockets.Client/tests/LoopbackServer/WebSocketHandshakeHelper.cs index e97d2feaf6f3b3..07e599949fbe0a 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/LoopbackServer/WebSocketHandshakeHelper.cs +++ b/src/libraries/System.Net.WebSockets.Client/tests/LoopbackServer/WebSocketHandshakeHelper.cs @@ -193,7 +193,7 @@ public static async Task SendHttp11ServerResponseAndEosAsync(WebSocketRequestDat } // send server EOS (half-closing from server side) - requestData.Http11Connection!.Socket.Shutdown(SocketShutdown.Send); + await requestData.Http11Connection!.Socket.ShutdownAsync(SocketShutdown.Send); } public static async Task SendHttp2ServerResponseAndEosAsync(WebSocketRequestData requestData, bool eosInHeadersFrame, Func? requestDataCallback, CancellationToken cancellationToken) diff --git a/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.Loopback.cs b/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.Loopback.cs index f54a4202d099d1..c786cce6160e01 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.Loopback.cs +++ b/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.Loopback.cs @@ -83,8 +83,8 @@ private async Task RunClient_SendReceive_ConnectionClosedPrematurely_ReceiveAsyn await pendingReceiveAsyncPosted.Task.WaitAsync(TimeSpan.FromMilliseconds(TimeOutMilliseconds)); // Close the underlying connection prematurely (without sending a WebSocket Close frame). - connection.Socket.Shutdown(SocketShutdown.Both); - connection.Socket.Close(); + await connection.Socket.ShutdownAsync(SocketShutdown.Both); + await connection.Socket.CloseAsync(); }); // Initiate a connection attempt.