WebOptimizer icon indicating copy to clipboard operation
WebOptimizer copied to clipboard

Asset.cs not thread safe

Open jertel opened this issue 5 years ago • 4 comments

Asset.GenerateCacheKey is modifying a standard (non-thread safe) Dictionary and doesn't appear to be protected by a thread mutex/lock. If multiple requests/threads attempt to access the same resource immediately after startup, it results in the Items dictionary becoming corrupt.

Ex:

System.InvalidOperationException: Operations that change non-concurrent collections must have exclusive access. A concurrent update was performed on this collection and corrupted its state. The collection's state is no longer correct.
    at System.Collections.Generic.Dictionary`2.FindEntry(TKey key)
    at System.Collections.Generic.Dictionary`2.ContainsKey(TKey key)
    at WebOptimizer.Asset.GenerateCacheKey(HttpContext context)
    at WebOptimizer.Taghelpers.BaseTagHelper.GenerateHash(IAsset asset)
    at WebOptimizer.Taghelpers.ScriptTagHelper.Process(TagHelperContext context, TagHelperOutput output)
    at Microsoft.AspNetCore.Razor.TagHelpers.TagHelper.ProcessAsync(TagHelperContext context, TagHelperOutput output)
    at Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner.RunAsync(TagHelperExecutionContext executionContext)

jertel avatar May 16 '19 17:05 jertel

I am seeing this happen in my production site as well

mbrennan376 avatar Nov 25 '19 01:11 mbrennan376

same here :(

erdemgezer avatar Jun 09 '20 07:06 erdemgezer

I'm getting the same error

Operations that change non-concurrent collections must have exclusive access. A concurrent update was performed on this collection and corrupted its state. The collection's state is no longer correct

at System.Collections.Generic.Dictionary`2.FindEntry(TKey key)\r\n   
at System.Collections.Generic.Dictionary`2.ContainsKey(TKey key)\r\n   
at WebOptimizer.Asset.GenerateCacheKey(HttpContext context)\r\n   
at WebOptimizer.Taghelpers.BaseTagHelper.GenerateHash(IAsset asset)\r\n   
at WebOptimizer.Taghelpers.LinkTagHelper.Process(TagHelperContext context, TagHelperOutput output)\r\n   at Microsoft.AspNetCore.Razor.TagHelpers.TagHelper.ProcessAsync(TagHelperContext context, TagHelperOutput output)\r\n   
at Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner.RunAsync(TagHelperExecutionContext executionContext)\r\n   at AspNetCore.Views_Shared__LayoutAdmin.<ExecuteAsync>b__22_0()\r\n   
at Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext.SetOutputContentAsync()\r\n   at AspNetCore.Views_Shared__LayoutAdmin.ExecuteAsync()\r\n   
at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context)\r\n   at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, Boolean invokeViewStarts)\r\n   
at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderLayoutAsync(ViewContext context, ViewBufferTextWriter bodyWriter)\r\n   
at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)\r\n   at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable`1 statusCode)\r\n  
at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable`1 statusCode)\r\n   
at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ActionContext actionContext, IView view, ViewDataDictionary viewData, ITempDataDictionary tempData, String contentType, Nullable`1 statusCode)\r\n   
at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor.ExecuteAsync(ActionContext context, ViewResult result)\r\n   
at Microsoft.AspNetCore.Mvc.ViewResult.ExecuteResultAsync(ActionContext context)\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|29_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n   
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()

Maybe change this Items to a ConcurrentDictionary would work?

/ m

enkelmedia avatar Dec 14 '20 10:12 enkelmedia

is there any update on this file? we have seen this issue twice this week, we have updated it from 3.0.250 to 3.0.311 but the issue is still there and we found it in this file. do we have a plan? also, there seems a breaking change thus we can't directly update to the latest version with no code change.

jasonliao-cb avatar Apr 06 '22 08:04 jasonliao-cb