I am getting a recurring error occuring in the Session_Start method in the Global.asax.cs file (ASP.NET, C#, .NET Framework 4). The error seems to be happening on the following line
if (!OnlineVisitorsUtility.Visitors.ContainsKey(currentContext.Session.SessionID))
which basically checks to see if this sessionId is in the current list of SessionIds.
The error is
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at TestSystem.WebSite.Global.Session_Start(Object sender, EventArgs e) Global.asax.cs:line 142
at System.Web.SessionState.SessionStateModule.CompleteAcquireState()
at System.Web.SessionState.SessionStateModule.BeginAcquireState(Object source, EventArgs e, AsyncCallback cb, Object extraData)
at System.Web.HttpApplication.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
There is no user logged against the error (because this is thrown before anybody logs in). But no user has reported errors attempting to log in, the only reason we see this is because it is showing up in the error logs.
The error occurs every minute or so for a few days, then stops for a few days before re-surfacing.
We record the remote host ip for each error, and it is different for each instance of the error I have looked at. I initially thought it was some sort of automated job kicking this off, but when I track the location IP address I have found it originating in places we have users, places we don’t and a private (i’m guessing internal) IP address.
We cannot replicate this error on our internal test and QA systems. I am looking for help in two areas, first, anyone have any idea what could be causing this, and second, if not, what information could I log that would shed some light on what’s causing this?
Thanks,
Neil
EDIT
The dictionary in the error trace above is a dictionary that stores a SessionId and a WebsiteVisitor class.
public static Dictionary<string, WebsiteVisitor> Visitors = new Dictionary<string, WebsiteVisitor>();
We only add to this after checking the ContainsKey if statement above. The whole statement is below
lock (visitorsLock)
{
if (!OnlineVisitorsUtility.Visitors.ContainsKey(currentContext.Session.SessionID))
{
OnlineVisitorsUtility.Visitors.Add(currentContext.Session.SessionID, new WebsiteVisitor(currentContext));
}
}
Sounds like you have a synchronization problem with your
Visitorsdictionary. The Dictionary collection is not thread-safe so read/write access needs to be controlled. I see your using a locking object to resolve this issue, however, the problem with that approach is IIS doesn’t guarantee that each request will be running under the same AppDomain instance or even the same worker process.Instead of cross thread locking you need to look at cross process locking, I would suggest using a Mutex.
Update
Actually @RichardDeeming made a very good point – the Visitors object won’t be shared across multiple processes/AppDomain so it can’t be a synchronisation problem in that respect, however, the Dictionary is getting corrupt somehow. I would recommend switching to using a ConcurrentDictionary and let the framework take care of the synchronisation for you.
Generally, static property in web apps aren’t a good idea as they can’t be shared across multiple AppDomains and you can end up running into mysterious issues like this.