Fixing race in distributed cache tag helper

Fixes #4407
This commit is contained in:
Sébastien Ros 2016-04-06 09:42:24 -07:00
parent c66c408c15
commit efb8ef33e6
3 changed files with 13 additions and 13 deletions

View File

@ -95,7 +95,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers.Cache
var serializedKey = Encoding.UTF8.GetBytes(key.GenerateKey());
var storageKey = key.GenerateHashedKey();
var value = await _storage.GetAsync(storageKey);
if (value == null)
{
// The value is not cached, we need to render the tag helper output
@ -126,7 +126,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers.Cache
// The value was found in the storage, decode and ensure
// there is no cache key hash collision
byte[] decodedValue = Decode(value, serializedKey);
try
{
if (decodedValue != null)
@ -147,21 +147,21 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers.Cache
}
}
}
// Notify all other awaiters of the final content
tcs.TrySetResult(content);
}
catch
{
// Notify all other awaiters to render the content
tcs.TrySetResult(null);
content = null;
throw;
}
finally
{
// Remove the worker task from the in-memory cache
Task<IHtmlContent> worker;
_workers.TryRemove(key, out worker);
// Remove the worker task before setting the result.
// If the result is null, other threads would potentially
// acquire it otherwise.
_workers.TryRemove(key, out result);
// Notify all other awaiters to render the content
tcs.TrySetResult(content);
}
}
else

View File

@ -67,7 +67,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
IHtmlContent content = null;
// Create a cancellation token that will be used
// Create a cancellation token that will be used
// to release the task from the memory cache.
var tokenSource = new CancellationTokenSource();
@ -109,6 +109,6 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
return options;
}
}
}

View File

@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
{
public class DistributedCacheTagHelperTest
{
[Fact]
public async Task ProcessAsync_DoesNotCache_IfDisabled()
{