Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Double lock pattern of ClientDependencySettings.Instance can result in null reference exception. #199

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

alan-strickland
Copy link

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:

System.Web.HttpUnhandledException (0x80004005): Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> System.NullReferenceException: Object reference not set to an instance of an object.
at ClientDependency.Core.ProviderDependencyList.ProviderIs(BaseFileRegistrationProvider provider) in C:\Users\Shannon\Documents\_Projects\ClientDependency\ClientDependency\ClientDependency.Core\ProviderDependencyList.cs:line 20
at System.Linq.Enumerable.WhereListIterator`1.MoveNext()
at System.Linq.Enumerable.<DefaultIfEmptyIterator>d__93`1.MoveNext()
at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source)
at ClientDependency.Core.BaseLoader.RegisterClientDependencies(BaseFileRegistrationProvider provider, IEnumerable`1 dependencies, IEnumerable`1 paths, ProviderCollection currProviders) in C:\Users\Shannon\Documents\_Projects\ClientDependency\ClientDependency\ClientDependency.Core\BaseLoader.cs:line 83
at ClientDependency.Core.BaseLoader.RegisterClientDependencies(List`1 dependencies, IEnumerable`1 paths) in C:\Users\Shannon\Documents\_Projects\ClientDependency\ClientDependency\ClientDependency.Core\BaseLoader.cs:line 154
at ClientDependency.Core.BaseLoader.RegisterDependency(Int32 group, Int32 priority, String filePath, String pathNameAlias, ClientDependencyType type, Object htmlAttributes, String provider, Boolean forceBundle) in C:\Users\Shannon\Documents\_Projects\ClientDependency\ClientDependency\ClientDependency.Core\BaseLoader.cs:line 307

The line that is throwing the exception is return Provider.Name == provider.Name; in ProviderDependencyList.

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.

…nsure there is no race condition when loading the Providers.
@Shazwazza
Copy link
Owner

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 if possible.

@alan-strickland
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants