Skip to content

Commit 17bd1da

Browse files
authored
Consistent ConfigureAwait on Loopback, RemoteExecutor.DisposeAsync (#102699)
* Add ConfigureAwait(false) to various place * Add RemoteExecutor.DisposeAsync and use it on System.Net.Mail * Add RemoteExecutor.DisposeAsync and use it on System.Net.Http * Add RemoteExecutor.DisposeAsync and use it on System.Net.Primitives * Add RemoteExecutor.DisposeAsync and use it on System.Net.Quic * Add RemoteExecutor.DisposeAsync and use it on System.Net.Requests * Add RemoteExecutor.DisposeAsync and use it on System.Net.Security * Add RemoteExecutor.DisposeAsync and use it on System.Net.Sockets * Add RemoteExecutor.DisposeAsync and use it on Common System.Net
1 parent 48f260e commit 17bd1da

File tree

55 files changed

+437
-384
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+437
-384
lines changed

src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs

+17-17
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public override async ValueTask DisposeAsync()
7575
// Dispose the connection
7676
// If we already waited for graceful shutdown from the client, then the connection is already closed and this will simply release the handle.
7777
// If not, then this will silently abort the connection.
78-
await _connection.DisposeAsync();
78+
await _connection.DisposeAsync().ConfigureAwait(false);
7979

8080
// Dispose control streams so that we release their handles too.
8181
if (_inboundControlStream is not null)
@@ -92,12 +92,12 @@ public override async ValueTask DisposeAsync()
9292

9393
public async ValueTask<Http3LoopbackStream> OpenUnidirectionalStreamAsync()
9494
{
95-
return new Http3LoopbackStream(await _connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional));
95+
return new Http3LoopbackStream(await _connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional).ConfigureAwait(false));
9696
}
9797

9898
public async ValueTask<Http3LoopbackStream> OpenBidirectionalStreamAsync()
9999
{
100-
return new Http3LoopbackStream(await _connection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional));
100+
return new Http3LoopbackStream(await _connection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional).ConfigureAwait(false));
101101
}
102102

103103
public static int GetRequestId(QuicStream stream)
@@ -141,10 +141,10 @@ async Task EnsureControlStreamAcceptedInternalAsync()
141141
_delayedStreams.Enqueue(quicStream);
142142
}
143143

144-
long? streamType = await controlStream.ReadIntegerAsync();
144+
long? streamType = await controlStream.ReadIntegerAsync().ConfigureAwait(false);
145145
Assert.Equal(Http3LoopbackStream.ControlStream, streamType);
146146

147-
List<(long settingId, long settingValue)> settings = await controlStream.ReadSettingsAsync();
147+
List<(long settingId, long settingValue)> settings = await controlStream.ReadSettingsAsync().ConfigureAwait(false);
148148
(long settingId, long settingValue) = Assert.Single(settings);
149149

150150
Assert.Equal(Http3LoopbackStream.MaxHeaderListSize, settingId);
@@ -177,17 +177,17 @@ public async Task<Http3LoopbackStream> AcceptRequestStreamAsync()
177177

178178
public async Task<(Http3LoopbackStream clientControlStream, Http3LoopbackStream requestStream)> AcceptControlAndRequestStreamAsync()
179179
{
180-
Http3LoopbackStream requestStream = await AcceptRequestStreamAsync();
180+
Http3LoopbackStream requestStream = await AcceptRequestStreamAsync().ConfigureAwait(false);
181181
Http3LoopbackStream controlStream = _inboundControlStream;
182182

183183
return (controlStream, requestStream);
184184
}
185185

186186
public async Task EstablishControlStreamAsync(SettingsEntry[] settingsEntries)
187187
{
188-
_outboundControlStream = await OpenUnidirectionalStreamAsync();
189-
await _outboundControlStream.SendUnidirectionalStreamTypeAsync(Http3LoopbackStream.ControlStream);
190-
await _outboundControlStream.SendSettingsFrameAsync(settingsEntries);
188+
_outboundControlStream = await OpenUnidirectionalStreamAsync().ConfigureAwait(false);
189+
await _outboundControlStream.SendUnidirectionalStreamTypeAsync(Http3LoopbackStream.ControlStream).ConfigureAwait(false);
190+
await _outboundControlStream.SendSettingsFrameAsync(settingsEntries).ConfigureAwait(false);
191191
}
192192

193193
public async Task DisposeCurrentStream()
@@ -213,7 +213,7 @@ public override async Task<HttpRequestData> ReadRequestDataAsync(bool readBody =
213213

214214
public override async Task SendResponseAsync(HttpStatusCode statusCode = HttpStatusCode.OK, IList<HttpHeaderData> headers = null, string content = "", bool isFinal = true)
215215
{
216-
await _currentStream.SendResponseAsync(statusCode, headers, content, isFinal);
216+
await _currentStream.SendResponseAsync(statusCode, headers, content, isFinal).ConfigureAwait(false);
217217
if (isFinal)
218218
{
219219
await DisposeCurrentStream().ConfigureAwait(false);
@@ -222,7 +222,7 @@ public override async Task SendResponseAsync(HttpStatusCode statusCode = HttpSta
222222

223223
public override async Task SendResponseBodyAsync(byte[] content, bool isFinal = true)
224224
{
225-
await _currentStream.SendResponseBodyAsync(content, isFinal);
225+
await _currentStream.SendResponseBodyAsync(content, isFinal).ConfigureAwait(false);
226226
if (isFinal)
227227
{
228228
await DisposeCurrentStream().ConfigureAwait(false);
@@ -249,11 +249,11 @@ public override async Task<HttpRequestData> HandleRequestAsync(HttpStatusCode st
249249
// So, send a GOAWAY frame now so the client won't inadvertantly try to reuse the connection.
250250
// Note that in HTTP3 (unlike HTTP2) there is no strict ordering between the GOAWAY and the response below;
251251
// so the client may race in processing them and we need to handle this.
252-
await _outboundControlStream.SendGoAwayFrameAsync(stream.StreamId + 4);
252+
await _outboundControlStream.SendGoAwayFrameAsync(stream.StreamId + 4).ConfigureAwait(false);
253253

254254
await stream.SendResponseAsync(statusCode, headers, content).ConfigureAwait(false);
255255

256-
await WaitForClientDisconnectAsync();
256+
await WaitForClientDisconnectAsync().ConfigureAwait(false);
257257

258258
return request;
259259
}
@@ -263,7 +263,7 @@ public async Task ShutdownAsync(bool failCurrentRequest = false)
263263
try
264264
{
265265
long firstInvalidStreamId = failCurrentRequest ? _currentStreamId : _currentStreamId + 4;
266-
await _outboundControlStream.SendGoAwayFrameAsync(firstInvalidStreamId);
266+
await _outboundControlStream.SendGoAwayFrameAsync(firstInvalidStreamId).ConfigureAwait(false);
267267
}
268268
catch (QuicException abortException) when (abortException.QuicError == QuicError.ConnectionAborted && abortException.ApplicationErrorCode == H3_NO_ERROR)
269269
{
@@ -283,7 +283,7 @@ public async Task ShutdownAsync(bool failCurrentRequest = false)
283283
return;
284284
}
285285

286-
await WaitForClientDisconnectAsync();
286+
await WaitForClientDisconnectAsync().ConfigureAwait(false);
287287
}
288288

289289
// Wait for the client to close the connection, e.g. after we send a GOAWAY, or after the HttpClient is disposed.
@@ -315,10 +315,10 @@ public async Task WaitForClientDisconnectAsync(bool refuseNewRequests = true)
315315

316316
// The client's control stream should throw QuicConnectionAbortedException, indicating that it was
317317
// aborted because the connection was closed (and was not explicitly closed or aborted prior to the connection being closed)
318-
QuicException ex = await Assert.ThrowsAsync<QuicException>(async () => await _inboundControlStream.ReadFrameAsync());
318+
QuicException ex = await Assert.ThrowsAsync<QuicException>(async () => await _inboundControlStream.ReadFrameAsync().ConfigureAwait(false));
319319
Assert.Equal(QuicError.ConnectionAborted, ex.QuicError);
320320

321-
await CloseAsync(H3_NO_ERROR);
321+
await CloseAsync(H3_NO_ERROR).ConfigureAwait(false);
322322
}
323323

324324
public override async Task WaitForCancellationAsync(bool ignoreIncomingData = true)

src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs

+5-6
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
using System.IO;
77
using System.Net.Quic;
88
using System.Net.Security;
9-
using System.Net.Sockets;
109
using System.Security.Cryptography.X509Certificates;
1110
using System.Threading.Tasks;
1211

@@ -71,13 +70,13 @@ private async Task<Http3LoopbackConnection> EstablishHttp3ConnectionAsync(params
7170
QuicConnection con = await _listener.AcceptConnectionAsync().ConfigureAwait(false);
7271
Http3LoopbackConnection connection = new Http3LoopbackConnection(con);
7372

74-
await connection.EstablishControlStreamAsync(settingsEntries);
73+
await connection.EstablishControlStreamAsync(settingsEntries).ConfigureAwait(false);
7574
return connection;
7675
}
7776

7877
public override async Task<GenericLoopbackConnection> EstablishGenericConnectionAsync()
7978
{
80-
return await EstablishHttp3ConnectionAsync();
79+
return await EstablishHttp3ConnectionAsync().ConfigureAwait(false);
8180
}
8281

8382
public Task<Http3LoopbackConnection> EstablishConnectionAsync(params SettingsEntry[] settingsEntries)
@@ -89,12 +88,12 @@ public override async Task AcceptConnectionAsync(Func<GenericLoopbackConnection,
8988
{
9089
await using Http3LoopbackConnection con = await EstablishHttp3ConnectionAsync().ConfigureAwait(false);
9190
await funcAsync(con).ConfigureAwait(false);
92-
await con.ShutdownAsync();
91+
await con.ShutdownAsync().ConfigureAwait(false);
9392
}
9493

9594
public override async Task<HttpRequestData> HandleRequestAsync(HttpStatusCode statusCode = HttpStatusCode.OK, IList<HttpHeaderData> headers = null, string content = "")
9695
{
97-
await using Http3LoopbackConnection con = (Http3LoopbackConnection)await EstablishGenericConnectionAsync().ConfigureAwait(false);
96+
await using Http3LoopbackConnection con = await EstablishHttp3ConnectionAsync().ConfigureAwait(false);
9897
return await con.HandleRequestAsync(statusCode, headers, content).ConfigureAwait(false);
9998
}
10099
}
@@ -113,7 +112,7 @@ public override GenericLoopbackServer CreateServer(GenericLoopbackOptions option
113112
public override async Task CreateServerAsync(Func<GenericLoopbackServer, Uri, Task> funcAsync, int millisecondsTimeout = LoopbackServerTimeoutMilliseconds, GenericLoopbackOptions options = null)
114113
{
115114
using GenericLoopbackServer server = CreateServer(options);
116-
await funcAsync(server, server.Address).WaitAsync(TimeSpan.FromMilliseconds(millisecondsTimeout));
115+
await funcAsync(server, server.Address).WaitAsync(TimeSpan.FromMilliseconds(millisecondsTimeout)).ConfigureAwait(false);
117116
}
118117

119118
public override Task<GenericLoopbackConnection> CreateConnectionAsync(SocketWrapper socket, Stream stream, GenericLoopbackOptions options = null)

src/libraries/Common/tests/System/Net/Http/Http3LoopbackStream.cs

+6-6
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ private async Task SendPartialHeadersFrameAsync(HttpStatusCode? statusCode, IEnu
124124
{
125125
Memory<byte> payload = ConstructHeadersPayload(statusCode, headers);
126126

127-
await SendFrameHeaderAsync(HeadersFrame, payload.Length);
127+
await SendFrameHeaderAsync(HeadersFrame, payload.Length).ConfigureAwait(false);
128128

129129
// Slice off final byte so the payload is not complete
130130
payload = payload.Slice(0, payload.Length - 1);
@@ -144,7 +144,7 @@ public async Task SendGoAwayFrameAsync(long firstInvalidStreamId)
144144
int bytesWritten = 0;
145145

146146
bytesWritten += EncodeHttpInteger(firstInvalidStreamId, buffer);
147-
await SendFrameAsync(GoAwayFrame, buffer.AsMemory(0, bytesWritten));
147+
await SendFrameAsync(GoAwayFrame, buffer.AsMemory(0, bytesWritten)).ConfigureAwait(false);
148148
}
149149

150150
private async Task SendFrameHeaderAsync(long frameType, int payloadLength)
@@ -367,11 +367,11 @@ async Task WaitForReadCancellation()
367367
{
368368
if (ignoreIncomingData)
369369
{
370-
await DrainResponseData();
370+
await DrainResponseData().ConfigureAwait(false);
371371
}
372372
else
373373
{
374-
int bytesRead = await _stream.ReadAsync(new byte[1]);
374+
int bytesRead = await _stream.ReadAsync(new byte[1]).ConfigureAwait(false);
375375
if (bytesRead != 0)
376376
{
377377
throw new Exception($"Unexpected data received while waiting for client cancllation.");
@@ -388,15 +388,15 @@ async Task WaitForWriteCancellation()
388388
{
389389
try
390390
{
391-
await _stream.WritesClosed;
391+
await _stream.WritesClosed.ConfigureAwait(false);
392392
}
393393
catch (QuicException ex) when (ex.QuicError == QuicError.StreamAborted && ex.ApplicationErrorCode == Http3LoopbackConnection.H3_REQUEST_CANCELLED)
394394
{
395395
writeCanceled = true;
396396
}
397397
}
398398

399-
await Task.WhenAll(WaitForReadCancellation(), WaitForWriteCancellation());
399+
await Task.WhenAll(WaitForReadCancellation(), WaitForWriteCancellation()).ConfigureAwait(false);
400400

401401
if (!readCanceled && !writeCanceled)
402402
{

src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.DefaultProxyCredentials.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,12 @@ public async Task ProxySetViaEnvironmentVariable_DefaultProxyCredentialsUsed(boo
9090
const string ExpectedPassword = "rightpassword";
9191
LoopbackServer.Options options = new LoopbackServer.Options { IsProxy = true, Username = ExpectedUsername, Password = ExpectedPassword };
9292

93-
await LoopbackServer.CreateClientAndServerAsync(uri => Task.Run(() =>
93+
await LoopbackServer.CreateClientAndServerAsync(uri => Task.Run(async () =>
9494
{
9595
var psi = new ProcessStartInfo();
9696
psi.Environment.Add("http_proxy", $"http://{uri.Host}:{uri.Port}");
9797

98-
RemoteExecutor.Invoke(async (useProxyString, useVersionString, uriString) =>
98+
await RemoteExecutor.Invoke(async (useProxyString, useVersionString, uriString) =>
9999
{
100100
using (HttpClientHandler handler = CreateHttpClientHandler(useVersionString))
101101
using (HttpClient client = CreateHttpClient(handler, useVersionString))
@@ -111,7 +111,7 @@ await LoopbackServer.CreateClientAndServerAsync(uri => Task.Run(() =>
111111
}, useProxy.ToString(), UseVersion.ToString(),
112112
// If proxy is used , the url does not matter. We set it to be different to avoid confusion.
113113
useProxy ? Configuration.Http.RemoteEchoServer.ToString() : uri.ToString(),
114-
new RemoteInvokeOptions { StartInfo = psi }).Dispose();
114+
new RemoteInvokeOptions { StartInfo = psi }).DisposeAsync();
115115
}),
116116
server => server.AcceptConnectionAsync(async connection =>
117117
{

src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ public async Task PostAsync_Post_ChannelBinding_ConfiguredCorrectly()
382382

383383
[ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
384384
[PlatformSpecific(TestPlatforms.Linux)]
385-
public void HttpClientUsesSslCertEnvironmentVariables()
385+
public async Task HttpClientUsesSslCertEnvironmentVariables()
386386
{
387387
// We set SSL_CERT_DIR and SSL_CERT_FILE to empty locations.
388388
// The HttpClient should fail to validate the server certificate.
@@ -395,7 +395,7 @@ public void HttpClientUsesSslCertEnvironmentVariables()
395395
File.WriteAllText(sslCertFile, "");
396396
psi.Environment.Add("SSL_CERT_FILE", sslCertFile);
397397

398-
RemoteExecutor.Invoke(async (useVersionString, allowAllCertificatesString) =>
398+
await RemoteExecutor.Invoke(async (useVersionString, allowAllCertificatesString) =>
399399
{
400400
const string Url = "https://www.microsoft.com";
401401
var version = Version.Parse(useVersionString);
@@ -405,7 +405,7 @@ public void HttpClientUsesSslCertEnvironmentVariables()
405405
using HttpClient client = CreateHttpClient(handler, useVersionString);
406406

407407
await Assert.ThrowsAsync<HttpRequestException>(() => client.GetAsync(Url));
408-
}, UseVersion.ToString(), AllowAllCertificates.ToString(), new RemoteInvokeOptions { StartInfo = psi }).Dispose();
408+
}, UseVersion.ToString(), AllowAllCertificates.ToString(), new RemoteInvokeOptions { StartInfo = psi }).DisposeAsync();
409409
}
410410
}
411411
}

src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using System.IO;
66
using System.Linq;
77
using System.Net.Http.Headers;
8-
using System.Net.Sockets;
98
#if !NETFRAMEWORK
109
using System.Net.Quic;
1110
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Threading.Tasks;
5+
using Microsoft.DotNet.RemoteExecutor;
6+
7+
namespace Microsoft.DotNet.RemoteExecutor;
8+
9+
internal static class RemoteExecutorExtensions
10+
{
11+
public static async ValueTask DisposeAsync(this RemoteInvokeHandle handle)
12+
{
13+
await Task.Run(handle.Dispose);
14+
}
15+
}

src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/System.Net.Http.WinHttpHandler.Functional.Tests.csproj

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
Link="Common\System\Net\EventSourceTestLogging.cs" />
3333
<Compile Include="$(CommonTestPath)System\Net\HttpsTestServer.cs"
3434
Link="Common\System\Net\HttpsTestServer.cs" />
35+
<Compile Include="$(CommonTestPath)System\Net\RemoteExecutorExtensions.cs"
36+
Link="Common\System\Net\RemoteExecutorExtensions.cs" />
3537
<Compile Include="$(CommonTestPath)System\Net\RemoteServerQuery.cs"
3638
Link="Common\System\Net\RemoteServerQuery.cs" />
3739
<Compile Include="$(CommonTestPath)System\Net\VerboseTestLogging.cs"

0 commit comments

Comments
 (0)