From 1839061e0d2ebeee44a2ed563bfe642f5b6796cd Mon Sep 17 00:00:00 2001 From: John Heffner Date: Thu, 22 Jul 2021 01:10:37 -0400 Subject: [PATCH] Avoid time domain casting exception during request cancellation (#2645) Context::Cancel() sets the deadline to DateTime::min(), which throws a range exception when cast to system_clock::time_point. Instead, cast system_clock::now() to DateTime. --- .../test/ut/storage_timeout_test.cpp | 14 ++++++++++++++ .../src/storage_per_retry_policy.cpp | 10 +++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/sdk/storage/azure-storage-blobs/test/ut/storage_timeout_test.cpp b/sdk/storage/azure-storage-blobs/test/ut/storage_timeout_test.cpp index b6b00f3d3..e86bc2418 100644 --- a/sdk/storage/azure-storage-blobs/test/ut/storage_timeout_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/ut/storage_timeout_test.cpp @@ -69,4 +69,18 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_LE(timeout.Value(), 301); } + TEST(StoragetimeoutTest, Cancelled) + { + Blobs::BlobClientOptions clientOptions; + auto containerClient = Azure::Storage::Blobs::BlobContainerClient::CreateFromConnectionString( + StandardStorageConnectionString(), LowercaseRandomString(), clientOptions); + + Azure::Core::Context context; + context.Cancel(); + // Should not throw an error on time point casting. + EXPECT_THROW( + containerClient.DeleteIfExists(Storage::Blobs::DeleteBlobContainerOptions(), context), + Core::OperationCancelledException); + } + }}} // namespace Azure::Storage::Test diff --git a/sdk/storage/azure-storage-common/src/storage_per_retry_policy.cpp b/sdk/storage/azure-storage-common/src/storage_per_retry_policy.cpp index b5520ee60..6799871da 100644 --- a/sdk/storage/azure-storage-common/src/storage_per_retry_policy.cpp +++ b/sdk/storage/azure-storage-common/src/storage_per_retry_policy.cpp @@ -37,11 +37,11 @@ namespace Azure { namespace Storage { namespace _internal { } else { - auto currentTimepoint = std::chrono::system_clock::now(); - int64_t numSeconds - = std::chrono::duration_cast( - std::chrono::system_clock::time_point(cancelTimepoint) - currentTimepoint) - .count(); + auto currentTimepoint = DateTime(std::chrono::system_clock::now()); + int64_t numSeconds = (cancelTimepoint > currentTimepoint) + ? std::chrono::duration_cast(cancelTimepoint - currentTimepoint) + .count() + : -1; request.GetUrl().AppendQueryParameter( HttpHeaderTimeout, std::to_string(std::max(numSeconds, int64_t(1)))); }