Skip to content

Commit 10d2b71

Browse files
authored
fix: Dispose HttpMessageHandler (#22)
1 parent 70d225a commit 10d2b71

File tree

9 files changed

+36
-38
lines changed

9 files changed

+36
-38
lines changed

src/Docker.DotNet.X509/X509Certificate2.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#if NETSTANDARD
1+
#if NETSTANDARD
22
namespace Docker.DotNet.X509.Polyfills;
33

44
using Org.BouncyCastle.Crypto;

src/Docker.DotNet/DockerClient.cs

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,15 @@ public sealed class DockerClient : IDockerClient
99

1010
private const string UserAgent = "Docker.DotNet";
1111

12-
private static readonly TimeSpan SInfiniteTimeout = Timeout.InfiniteTimeSpan;
13-
1412
private readonly HttpClient _client;
1513

1614
private readonly Uri _endpointBaseUri;
1715

1816
private readonly Version _requestedApiVersion;
1917

20-
private readonly ILogger _logger;
21-
2218
internal DockerClient(DockerClientConfiguration configuration, Version requestedApiVersion, ILogger logger = null)
2319
{
2420
_requestedApiVersion = requestedApiVersion;
25-
_logger = logger ?? NullLogger.Instance;
2621

2722
Configuration = configuration;
2823
DefaultTimeout = configuration.DefaultTimeout;
@@ -75,7 +70,7 @@ await stream.ConnectAsync(timeout, cancellationToken)
7570
.ConfigureAwait(false);
7671

7772
return dockerStream;
78-
}, _logger);
73+
}, logger);
7974
break;
8075

8176
case "tcp":
@@ -85,11 +80,11 @@ await stream.ConnectAsync(timeout, cancellationToken)
8580
Scheme = configuration.Credentials.IsTlsCredentials() ? "https" : "http"
8681
};
8782
uri = builder.Uri;
88-
handler = new ManagedHandler(_logger);
83+
handler = new ManagedHandler(logger);
8984
break;
9085

9186
case "https":
92-
handler = new ManagedHandler(_logger);
87+
handler = new ManagedHandler(logger);
9388
break;
9489

9590
case "unix":
@@ -102,7 +97,7 @@ await sock.ConnectAsync(new Microsoft.Net.Http.Client.UnixDomainSocketEndPoint(p
10297
.ConfigureAwait(false);
10398

10499
return sock;
105-
}, _logger);
100+
}, logger);
106101
uri = new UriBuilder("http", uri.Segments.Last()).Uri;
107102
break;
108103

@@ -113,7 +108,7 @@ await sock.ConnectAsync(new Microsoft.Net.Http.Client.UnixDomainSocketEndPoint(p
113108
_endpointBaseUri = uri;
114109

115110
_client = new HttpClient(Configuration.Credentials.GetHandler(handler), true);
116-
_client.Timeout = SInfiniteTimeout;
111+
_client.Timeout = Timeout.InfiniteTimeSpan;
117112
}
118113

119114
public DockerClientConfiguration Configuration { get; }
@@ -299,7 +294,7 @@ internal Task<Stream> MakeRequestForStreamAsync(
299294
IDictionary<string, string> headers,
300295
CancellationToken token)
301296
{
302-
return MakeRequestForStreamAsync(errorHandlers, method, path, queryString, body, headers, SInfiniteTimeout, token);
297+
return MakeRequestForStreamAsync(errorHandlers, method, path, queryString, body, headers, Timeout.InfiniteTimeSpan, token);
303298
}
304299

305300
internal async Task<Stream> MakeRequestForStreamAsync(
@@ -330,7 +325,7 @@ internal async Task<HttpResponseMessage> MakeRequestForRawResponseAsync(
330325
IDictionary<string, string> headers,
331326
CancellationToken token)
332327
{
333-
var response = await PrivateMakeRequestAsync(SInfiniteTimeout, HttpCompletionOption.ResponseHeadersRead, method, path, queryString, headers, body, token)
328+
var response = await PrivateMakeRequestAsync(Timeout.InfiniteTimeSpan, HttpCompletionOption.ResponseHeadersRead, method, path, queryString, headers, body, token)
334329
.ConfigureAwait(false);
335330

336331
await HandleIfErrorResponseAsync(response.StatusCode, response)
@@ -346,7 +341,7 @@ internal async Task<DockerApiStreamedResponse> MakeRequestForStreamedResponseAsy
346341
IQueryString queryString,
347342
CancellationToken cancellationToken)
348343
{
349-
var response = await PrivateMakeRequestAsync(SInfiniteTimeout, HttpCompletionOption.ResponseHeadersRead, method, path, queryString, null, null, cancellationToken)
344+
var response = await PrivateMakeRequestAsync(Timeout.InfiniteTimeSpan, HttpCompletionOption.ResponseHeadersRead, method, path, queryString, null, null, cancellationToken)
350345
.ConfigureAwait(false);
351346

352347
await HandleIfErrorResponseAsync(response.StatusCode, response, errorHandlers)
@@ -367,7 +362,7 @@ internal Task<WriteClosableStream> MakeRequestForHijackedStreamAsync(
367362
IDictionary<string, string> headers,
368363
CancellationToken cancellationToken)
369364
{
370-
return MakeRequestForHijackedStreamAsync(errorHandlers, method, path, queryString, body, headers, SInfiniteTimeout, cancellationToken);
365+
return MakeRequestForHijackedStreamAsync(errorHandlers, method, path, queryString, body, headers, Timeout.InfiniteTimeSpan, cancellationToken);
371366
}
372367

373368
internal async Task<WriteClosableStream> MakeRequestForHijackedStreamAsync(
@@ -418,24 +413,26 @@ private async Task<HttpResponseMessage> PrivateMakeRequestAsync(
418413
IRequestContent data,
419414
CancellationToken cancellationToken)
420415
{
421-
var request = PrepareRequest(method, path, queryString, headers, data);
416+
using var request = PrepareRequest(method, path, queryString, headers, data);
422417

423-
if (timeout != SInfiniteTimeout)
418+
if (Timeout.InfiniteTimeSpan == timeout)
424419
{
425-
using (var timeoutTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
426-
{
427-
timeoutTokenSource.CancelAfter(timeout);
428-
return await _client.SendAsync(request, completionOption, timeoutTokenSource.Token)
429-
.ConfigureAwait(false);
430-
}
431-
}
420+
var tcs = new TaskCompletionSource<HttpResponseMessage>();
421+
422+
using var disposable = cancellationToken.Register(() => tcs.SetCanceled());
432423

433-
var tcs = new TaskCompletionSource<HttpResponseMessage>();
434-
using (cancellationToken.Register(() => tcs.SetCanceled()))
435-
{
436424
return await await Task.WhenAny(tcs.Task, _client.SendAsync(request, completionOption, cancellationToken))
437425
.ConfigureAwait(false);
438426
}
427+
else
428+
{
429+
using var timeoutCts = new CancellationTokenSource(timeout);
430+
431+
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(timeoutCts.Token, cancellationToken);
432+
433+
return await _client.SendAsync(request, completionOption, linkedCts.Token)
434+
.ConfigureAwait(false);
435+
}
439436
}
440437

441438
private HttpRequestMessage PrepareRequest(HttpMethod method, string path, IQueryString queryString, IDictionary<string, string> headers, IRequestContent data)

src/Docker.DotNet/DockerClientConfiguration.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ public DockerClientConfiguration(
3232

3333
EndpointBaseUri = endpoint;
3434
Credentials = credentials ?? new AnonymousCredentials();
35-
DefaultTimeout = TimeSpan.Equals(default, defaultTimeout) ? TimeSpan.FromSeconds(100) : defaultTimeout;
36-
NamedPipeConnectTimeout = TimeSpan.Equals(default, namedPipeConnectTimeout) ? TimeSpan.FromMilliseconds(100) : namedPipeConnectTimeout;
35+
DefaultTimeout = TimeSpan.Equals(TimeSpan.Zero, defaultTimeout) ? TimeSpan.FromSeconds(100) : defaultTimeout;
36+
NamedPipeConnectTimeout = TimeSpan.Equals(TimeSpan.Zero, namedPipeConnectTimeout) ? TimeSpan.FromMilliseconds(100) : namedPipeConnectTimeout;
3737
DefaultHttpRequestHeaders = defaultHttpRequestHeaders ?? new Dictionary<string, string>();
3838
}
3939

src/Docker.DotNet/DockerPipeStream.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ protected override void Dispose(bool disposing)
126126
{
127127
if (disposing)
128128
{
129-
_stream.Dispose();
130129
_event.Dispose();
130+
_stream.Dispose();
131131
}
132132
}
133133
}

src/Docker.DotNet/Endpoints/ContainerOperations.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ public async Task<ContainerWaitResponse> WaitContainerAsync(string id, Cancellat
318318
throw new ArgumentNullException(nameof(id));
319319
}
320320

321-
return await _client.MakeRequestAsync<ContainerWaitResponse>(new[] { NoSuchContainerHandler }, HttpMethod.Post, $"containers/{id}/wait", null, null, null, TimeSpan.FromMilliseconds(Timeout.Infinite), cancellationToken).ConfigureAwait(false);
321+
return await _client.MakeRequestAsync<ContainerWaitResponse>(new[] { NoSuchContainerHandler }, HttpMethod.Post, $"containers/{id}/wait", null, null, null, Timeout.InfiniteTimeSpan, cancellationToken).ConfigureAwait(false);
322322
}
323323

324324
public Task RemoveContainerAsync(string id, ContainerRemoveParameters parameters, CancellationToken cancellationToken = default)

src/Docker.DotNet/Microsoft.Net.Http.Client/HttpConnectionResponseContent.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ protected override void Dispose(bool disposing)
6363
if (disposing)
6464
{
6565
_responseStream.Dispose();
66+
_connection.Dispose();
6667
}
6768
}
6869
finally

test/Docker.DotNet.Tests/CommonCommands.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace Docker.DotNet.Tests;
1+
namespace Docker.DotNet.Tests;
22

33
public static class CommonCommands
44
{

test/Docker.DotNet.Tests/IContainerOperationsTests.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -655,9 +655,11 @@ public async Task StartContainerAsync_ContainerNotExists_ThrowsException()
655655
[Fact]
656656
public async Task WaitContainerAsync_TokenIsCancelled_OperationCancelledException()
657657
{
658+
using var waitContainerCts = CancellationTokenSource.CreateLinkedTokenSource(_testFixture.Cts.Token);
659+
658660
var stopWatch = new Stopwatch();
659661

660-
using var waitContainerCts = new CancellationTokenSource(delay: TimeSpan.FromMinutes(5));
662+
var delay = TimeSpan.FromSeconds(5);
661663

662664
var createContainerResponse = await _testFixture.DockerClient.Containers.CreateContainerAsync(
663665
new CreateContainerParameters
@@ -674,12 +676,10 @@ public async Task WaitContainerAsync_TokenIsCancelled_OperationCancelledExceptio
674676

675677
_testOutputHelper.WriteLine("Starting timeout to cancel WaitContainer operation.");
676678

677-
TimeSpan delay = TimeSpan.FromSeconds(5);
678-
679679
waitContainerCts.CancelAfter(delay);
680680
stopWatch.Start();
681681

682-
// Will wait forever here if cancelation fails.
682+
// Will wait forever here if cancellation fails.
683683
var waitContainerTask = _testFixture.DockerClient.Containers.WaitContainerAsync(createContainerResponse.ID, waitContainerCts.Token);
684684

685685
_ = await Assert.ThrowsAsync<TaskCanceledException>(() => waitContainerTask);
@@ -690,7 +690,7 @@ public async Task WaitContainerAsync_TokenIsCancelled_OperationCancelledExceptio
690690
_testOutputHelper.WriteLine($"WaitContainerAsync: {stopWatch.Elapsed} elapsed");
691691

692692
// Task should be cancelled when CancelAfter timespan expires
693-
TimeSpan tolerance = TimeSpan.FromMilliseconds(500);
693+
var tolerance = TimeSpan.FromMilliseconds(500);
694694

695695
Assert.InRange(stopWatch.Elapsed, delay.Subtract(tolerance), delay.Add(tolerance));
696696
Assert.True(waitContainerTask.IsCanceled);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{
1+
{
22
"$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
33
"diagnosticMessages" : false
44
}

0 commit comments

Comments
 (0)