Skip to content

Commit 597a9a7

Browse files
Dispose fixes on download (Azure#46592)
* dispose fixes * changelog * grammar * feedback
1 parent 4160653 commit 597a9a7

File tree

3 files changed

+16
-2
lines changed

3 files changed

+16
-2
lines changed

sdk/storage/Azure.Storage.Blobs/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
### Breaking Changes
88

99
### Bugs Fixed
10+
- Fixed bug where network download streams were not properly disposed.
11+
- Fixed bug where DownloadToAsync() did not dispose all its network streams on error in some cases.
1012

1113
### Other Changes
1214

sdk/storage/Azure.Storage.Blobs/src/BlobBaseClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1572,7 +1572,7 @@ internal virtual async ValueTask<Response<BlobDownloadStreamingResult>> Download
15721572
ClientConfiguration.Pipeline.ResponseClassifier,
15731573
Constants.MaxReliabilityRetries);
15741574

1575-
stream = stream.WithNoDispose().WithProgress(progressHandler);
1575+
stream = stream.WithProgress(progressHandler);
15761576

15771577
/* Decryption handled by caller, so safe to check checksum now.
15781578
* Buffer response stream and ensure it matches the transactional checksum if any.

sdk/storage/Azure.Storage.Blobs/src/PartitionedDownloader.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Collections.Generic;
77
using System.Globalization;
88
using System.IO;
9+
using System.Linq;
910
using System.Threading;
1011
using System.Threading.Tasks;
1112
using Azure.Core;
@@ -144,6 +145,7 @@ public async Task<Response> DownloadToInternal(
144145
// tracing
145146
DiagnosticScope scope = _client.ClientConfiguration.ClientDiagnostics.CreateScope(_operationName);
146147
using DisposableBucket disposables = new DisposableBucket();
148+
Queue<Task<Response<BlobDownloadStreamingResult>>> runningTasks = null;
147149
try
148150
{
149151
scope.Start();
@@ -230,7 +232,6 @@ await HandleOneShotDownload(initialResponse, destination, async, cancellationTok
230232
#pragma warning disable AZC0110 // DO NOT use await keyword in possibly synchronous scope.
231233
// Rule checker cannot understand this section, but this
232234
// massively reduces code duplication.
233-
Queue<Task<Response<BlobDownloadStreamingResult>>> runningTasks = null;
234235
int effectiveWorkerCount = async ? _maxWorkerCount : 1;
235236
if (effectiveWorkerCount > 1)
236237
{
@@ -354,6 +355,17 @@ await CopyToInternal(
354355
}
355356
finally
356357
{
358+
#pragma warning disable AZC0110
359+
if (runningTasks != null)
360+
{
361+
async Task DisposeStreamAsync(Task<Response<BlobDownloadStreamingResult>> task)
362+
{
363+
Response<BlobDownloadStreamingResult> response = await task.ConfigureAwait(false);
364+
response.Value.Content.Dispose();
365+
}
366+
await Task.WhenAll(runningTasks.Select(DisposeStreamAsync)).ConfigureAwait(false);
367+
}
368+
#pragma warning restore AZC0110
357369
scope.Dispose();
358370
}
359371
}

0 commit comments

Comments
 (0)