We are getting random System.NullReferenceException in our ASP.NET web application. We are using inproc session state. Stacktrace:
System.NullReferenceException: Object reference not set to an instance of an object.
at System.Collections.Specialized.NameObjectCollectionBase.BaseRemove(String name)
at System.Web.SessionState.SessionStateItemCollection.Remove(String name)
at System.Web.SessionState.HttpSessionStateContainer.Remove(String name)
at System.Web.UI.SessionPageStatePersister.Save()
at System.Web.UI.Page.SaveAllState()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
The problem seems to come from Page.PageStatePersister property which we have overriden like this.
protected override PageStatePersister PageStatePersister {
get {
return new SessionPageStatePersister(Page);
}
}
Reflector showed that SessionPageStatePersister internally calls Session.Remove.
We are getting similar random NullReferenceException while calling Session.Remove directly on Page. Relevant stacktrace:
---> System.NullReferenceException: Object reference not set to an instance of an object.
at System.Collections.Specialized.NameObjectCollectionBase.BaseRemove(String name)
at System.Web.SessionState.SessionStateItemCollection.Remove(String name)
at System.Web.SessionState.HttpSessionStateContainer.Remove(String name)
at System.Web.SessionState.HttpSessionState.Remove(String name)
at PERH.WebFramework.Bases.PageBase.OnPreInit(EventArgs e) in
Any idea, what might cause those exceptions?
Environment:
IIS6, Windows Server 2003 64-bit, .net Framework 3.5
The issue may occur when the requests made by the same user (from the same session ID) are processed concurrently.
This is because System.Web.SessionState.SessionStateItemCollection
doesn't check the entry to be null when removing it.
In the System.Web.SessionState.SessionStateItemCollection.Remove(string name)
method the lock is set on the private collection _serializedItems
so that Remove operation is thread safe. Yet this private collection doesn't get locked during Add operations. Considering that _serializedItems
behaves as a resizing array (when entries count is >= 1/2 of its capacity the capacity is doubled and new entries are filled with nulls) concurrent addition may result into situations when null values remain in the middle of the collection.
The entries only get removed from [0; entries count] range of the _serializedItems
collection. When removing the entry its Key
property gets accessed without null checking. Thus if null entry form the middle of the collection is removed the NullReferenceException
gets cast.
By default all requests with same session ID are processed sequentially unless System.Web.Configuration.PagesSection.EnableSessionState
is explicitly set to ReadOnly
.
In this case any operation that involves adding values into System.Web.SessionState.HttpSessionState
(which internally uses System.Web.SessionState.HttpSessionStateContainer
which in turn internally uses System.Web.SessionState.SessionStateItemCollection
) should be properly locked to assure thread safety.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With