Open alan-strickland opened 3 years ago
Thanks @alan-strickland . The memory barrier is curious because the _settings is marked volatile so there should be a memory barrier in there already. But also your fix relies on an HttpContext to be there too?
This is an old project but agree it's simpler to use Lazy
You're right I had missed the volatile keyword the memory barrier is not required.
I think it can rely on HttpContext
because the empty constructor is also dependent on HttpContext
and throws
InvalidOperationException
if HttpContext.Current
is null. So I didn't think I was introducing a dependency that didn't already exist.
Something I can't understand is why private static Action _loadProviders = null
is required. The method _loadProviders is called from each constructor apart from the empty constructor which is only used by the static property Instance
which also calls _loadProviders
, couldn't all the constructors just call LoadProviders.
As you say though its an old project and I didn't want to refactor it too much to resolve the problem I had.
We recently had an issue with a asp.net web forms site that utilises this library where IIS was repeatedly crashing. This library did not cause the crash however it did highlight an issue with ClientDependencySettings and the Instance property where the double lock pattern was not safely implemented and could result in a thread throwing a null reference exception on the Providers property.
Example exception call stack:
The line that is throwing the exception is
return Provider.Name == provider.Name;
inProviderDependencyList
.To resolve this I am calling the
LoadProviders
method prior to assigning the new settings instance to the_settings
field.It might be better to use
Lazy<>
here instead and remove the double lock pattern altogether, but the change as it is resolved the issue we had.