Skip to content

Commit

Permalink
Dispose fixes on download (#46592)
Browse files Browse the repository at this point in the history
* dispose fixes

* changelog

* grammar

* feedback
  • Loading branch information
jaschrep-msft authored Oct 28, 2024
1 parent 4160653 commit 597a9a7
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 2 deletions.
2 changes: 2 additions & 0 deletions sdk/storage/Azure.Storage.Blobs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
### Breaking Changes

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

### Other Changes

Expand Down
2 changes: 1 addition & 1 deletion sdk/storage/Azure.Storage.Blobs/src/BlobBaseClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1572,7 +1572,7 @@ internal virtual async ValueTask<Response<BlobDownloadStreamingResult>> Download
ClientConfiguration.Pipeline.ResponseClassifier,
Constants.MaxReliabilityRetries);

stream = stream.WithNoDispose().WithProgress(progressHandler);
stream = stream.WithProgress(progressHandler);

/* Decryption handled by caller, so safe to check checksum now.
* Buffer response stream and ensure it matches the transactional checksum if any.
Expand Down
14 changes: 13 additions & 1 deletion sdk/storage/Azure.Storage.Blobs/src/PartitionedDownloader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Azure.Core;
Expand Down Expand Up @@ -144,6 +145,7 @@ public async Task<Response> DownloadToInternal(
// tracing
DiagnosticScope scope = _client.ClientConfiguration.ClientDiagnostics.CreateScope(_operationName);
using DisposableBucket disposables = new DisposableBucket();
Queue<Task<Response<BlobDownloadStreamingResult>>> runningTasks = null;
try
{
scope.Start();
Expand Down Expand Up @@ -230,7 +232,6 @@ await HandleOneShotDownload(initialResponse, destination, async, cancellationTok
#pragma warning disable AZC0110 // DO NOT use await keyword in possibly synchronous scope.
// Rule checker cannot understand this section, but this
// massively reduces code duplication.
Queue<Task<Response<BlobDownloadStreamingResult>>> runningTasks = null;
int effectiveWorkerCount = async ? _maxWorkerCount : 1;
if (effectiveWorkerCount > 1)
{
Expand Down Expand Up @@ -354,6 +355,17 @@ await CopyToInternal(
}
finally
{
#pragma warning disable AZC0110
if (runningTasks != null)
{
async Task DisposeStreamAsync(Task<Response<BlobDownloadStreamingResult>> task)
{
Response<BlobDownloadStreamingResult> response = await task.ConfigureAwait(false);
response.Value.Content.Dispose();
}
await Task.WhenAll(runningTasks.Select(DisposeStreamAsync)).ConfigureAwait(false);
}
#pragma warning restore AZC0110
scope.Dispose();
}
}
Expand Down

0 comments on commit 597a9a7

Please sign in to comment.