3
votes

Recently we have been encountering the following problem in production when reading our configuration file.

Object reference not set to an instance of an object. (C:\applications\SampleWebsite\web.config line 105) at at System.Configuration.BaseConfigurationRecord.EvaluateOne(String[] keys, SectionInput input, Boolean isTrusted, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentResult) at System.Configuration.BaseConfigurationRecord.Evaluate(FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentResult, Boolean getLkg, Boolean getRuntimeObject, Object& result, Object& resultRuntimeObject) at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject) at System.Configuration.BaseConfigurationRecord.GetSection(String configKey) at System.Configuration.ConfigurationManager.GetSection(String sectionName) at SampleWebsite.Configuration.CustomConfigurationSection.get_Current() in c:\Builds\1\SampleWebsite\Sources\Source\SampleWebsite\Configuration\CustomConfigurationSection.cs:line 69 at SampleWebsite.Security.AuthorizationManager.CheckAccess(AuthorizationContext context) in c:\Builds\1\SampleWebsite\Sources\Source\SampleWebsite\Security\AuthorizationManager.cs:line 161 at System.IdentityModel.Services.ClaimsPrincipalPermission.Demand() at System.Security.PermissionSet.DemandNonCAS() at SampleWebsite.CustomController.Test() in c:\Builds\1\SampleWebsite\Sources\Source\SampleWebsite\Controllers\CustomController.cs:line 125 at lambda_method(Closure , Object , Object[] ) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c_DisplayClass13.b_c(Object instance, Object[] methodParameters) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments) at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken)

We are using .NET 4.5 on IIS 8 on a Windows Server 2012. The issue sometimes (not always!) occurs after the recycle of the application pool. If the issue occurs, we have to stop our application pool and start our application pool. Recycling the application pool does not help, neither does restarting the website.

Nothing was changed in the configuration file. The only real difference we have noticed is that there are more requests made to the website itself.

Since we first thought it could have been a race condition, we have scheduled the application pool to recycle at a specific time when we are sure that no requests are being send to the website.

The recycle time has been chosen at a time when the applications that send requests to this site are shut down and before they are started up again.

The application pool has the following configuration options set:

  • Start Automatically: true
  • Start Mode: AlwaysRunning
  • Start application pool immediately: true

The website has the following options set:

  • Preload Enabled: true
  • Start automatically: true

Has anyone encountered this issue before?

Any help would be greatly appreciated!

EDIT:

This is basically what's in the custom config section code:

public sealed class CustomConfigurationSection : ConfigurationSection
{
    private static CustomConfigurationSection _current;

    public static CustomConfigurationSection Current
    {
        get
        {
            return _current
                ?? (_current = ConfigurationManager.GetSection(CustomSectionName) as CustomConfigurationSection);
        }
    }
}

The nullref occurs in the ConfigurationManager.GetSection() after the app pool is recycled and the _current field (a static) is nullified and needs to be read again from the config file.

1
What's in CustomConfigurationSection.cs? - CodingIntrigue
@Soner OP knows what a nullref is. We just don't know why the custom config section is null at random times. 99% of the time, the section is read correctly. 1% of the time it barfs for no apparent reason and with no changes at all in the config file - stombeur
@RGraham, see edit in the question. Is this enough info? - stombeur

1 Answers

3
votes

The null coalescing operator you are using is not thread safe. Add a locking variable to your getter:

private static CustomConfigurationSection _current;
private static readonly object _lock = new object();

public static CustomConfigurationSection Current
{
    get
    {
        lock(_lock) {
            return _current
                ?? (_current = ConfigurationManager.GetSection(CustomSectionName) as CustomConfigurationSection);
        }
    }
}

It's also possible that the ConfigurationManager isn't returning the expected value shortly after the recycle of the application pool (I can't see where CustomSectionName is defined). It might be worth adding a check here to ensure that you are actually returning the expected section.

It may also be worth setting the static property inside the constructor of the CustomConfigurationSection:

public sealed class CustomConfigurationSection : ConfigurationSection
{
    public CustomConfigurationSection() {
        Current = CurrentConfiguration.GetSection(CustomSectionName);
    }

    public static CustomConfigurationSection Current { get; private set; }
}