1

I am getting an error that doesn't happen very often, but the client has seen it and wants it fixed.

Basically, it's an IndexOutOfRangeException exception, but what's odd is that the trace points to System.Web.HttpContext.Current. How is that possible?

The line that it fails on is like this:


at System.Collections.ArrayList.Add(Object value) at System.Collections.Specialized.NameObjectCollectionBase.BaseAdd(String name, Object value) at System.Web.SessionState.SessionStateItemCollection.set_Item(String name, Object value) at WebStateManager.set_Item(String key, Object value) in \WebStateManager.cs:line 53 at UIStateManager.get_BookingParameters() in WS\App_Code\Managers\UIStateManager.cs:line 2746
Index was outside the bounds of the array.

System.Web.HttpContext context = System.Web.HttpContext.Current;

If it was an array, I could do counts and other checks, but what kind of check would I do here other than a try-catch? enter link description here

public class Example
{
   public static void Main()
   {
      int[] values1 = { 3, 6, 9, 12, 15, 18, 21 };
      int[] values2 = new int[6];

      // Assign last element of the array to the new array.
      values2[values1.Length - 1] = values1[values1.Length - 1];
   }
}
// The example displays the following output:
//       Unhandled Exception: 
//       System.IndexOutOfRangeException: 
//       Index was outside the bounds of the array.
//       at Example.Main()

My Project Code

public override object this[string key]
        {
            get
            {
                if (Helpers.CommonFunctions.IsHttpSessionNull)
                { return null; }

                return HttpContext.Current.Session[key + Helpers.CommonFunctions.GetAppDomainMultiplexer()];
            }
            set
            {
                if (Helpers.CommonFunctions.IsHttpSessionNull)
                { return; }

                if (value == null)
                {
                    try
                    {
                        if (HttpContext.Current.Session[key + Helpers.CommonFunctions.GetAppDomainMultiplexer()] != null)
                        {
                            HttpContext.Current.Session.Remove(key + Helpers.CommonFunctions.GetAppDomainMultiplexer());
                        }
                    }
                    catch
                    {
                    }
                }
                else
                {
                        HttpContext.Current.Session[key + Helpers.CommonFunctions.GetAppDomainMultiplexer()] = value;

                }
            }
        }

The fault stack trace is as follows;

0:072> !clrstack
    OS Thread Id: 0x31ec (72)
            Child SP               IP Call Site
    000000aea766d968 000007f9736a4650 [HelperMethodFrame: 000000aea766d968] 
    000000aea766da50 000007f9674e0e5a System.Collections.ArrayList.Add(System.Object)
    000000aea766da90 000007f966655292 System.Collections.Specialized.NameObjectCollectionBase.BaseAdd(System.String, System.Object)
    000000aea766dae0 000007f9650ac4c9 System.Web.SessionState.SessionStateItemCollection.set_Item(System.String, System.Object)
    000000aea766db20 000007f90ed89ce9 UTL.WebStateManager.set_Item(System.String, System.Object)
    000000aea766dbf0 000007f90f29370c WebStateManagerHelper.get_OriginalPNR()
    000000aea766dc80 000007f90f29242d QueryDynamicLoggingComponent.LogTransaction(System.String, System.String)
    000000aea766e110 000007f90f2917e3 WSHelper.Log(System.String, System.String, Boolean, System.String)
    000000aea766e160 000007f90f28fd17 WSHelper.GetResponse(System.String, SecurityInfo, System.String, System.String, System.String ByRef, System.String, System.String)
    000000aea766e5d0 000007f90f29eae6 WSHelper.SendQuery(System.String, SecurityInfo, System.String)
    000000aea766e7f0 000007f90f29e7f8 WSHelper.SendQuery(SecurityInfo, System.String)
    000000aea766e840 000007f90f29e4af APIWSPool.SendAndReceiveQueryToString(Agency, System.String, Token, Boolean)
    000000aea766e940 000007f90f29e374 APIWSPool.SendAndReceiveQuery(Agency, Token, Boolean)
    000000aea766e9b0 000007f90f6168f4 FlightBookingManager.SearchFlightForMPSearchedFlightRecommendations1(Agency, FlightFareDrivenSearchInfo, Boolean)
    000000aea766eb80 000007f90f615ec1 ApiFlightBookingProvider.SearchFlightForMPSearchedFlightRecommendations1(Agency, FlightFareDrivenSearchInfo, Boolean)
    000000aea766ebe0 000007f90f6158f2 APICOM.Threading.OWCOutboundSearchThread.Work()
    000000aea766edb0 000007f9674e2d45 System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
    000000aea766ef10 000007f9674e2ab9 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
    000000aea766ef40 000007f9674e2a97 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
    000000aea766ef90 000007f9674fa161 System.Threading.ThreadHelper.ThreadStart()
    000000aea766f2a8 000007f96e0eab53 [GCFrame: 000000aea766f2a8] 
    000000aea766f5f8 000007f96e0eab53 [DebuggerU2MCatchHandlerFrame: 000000aea766f5f8] 
    000000aea766f788 000007f96e0eab53 [ContextTransitionFrame: 000000aea766f788] 
    000000aea766f9a8 000007f96e0eab53 [DebuggerU2MCatchHandlerFrame: 000000aea766f9a8] 
Onur Dikmen
  • 339
  • 1
  • 6
  • 17

1 Answers1

1

SessionStateItemCollection is not thread-safe (see https://msdn.microsoft.com/en-us/library/system.web.sessionstate.sessionstateitemcollection(v=vs.110).aspx), and you likely have multiple threads writing / reading from the session state at the same time.

You need to find your code that accesses HttpContext.Session or Page.Session and make sure that code is not running in a background thread.

See https://msdn.microsoft.com/en-us/library/system.indexoutofrangeexception(v=vs.110).aspx - (search for "Violating thread safety")

Below is some example code using locking to try and avoid the issue. This code is very quick and dirty. I do not recommend it. But short of re-architecting your system, it may be worthwhile. If you use this technique, you must put it around every use of Session.

    public override object this[string key]
    {
        get
        {
            if (Helpers.CommonFunctions.IsHttpSessionNull)
            { return null; }

            lock (HttpContext.Current.Session)
            { 
                return HttpContext.Current.Session[key + Helpers.CommonFunctions.GetAppDomainMultiplexer()];
            }
        }
        set
        {
            if (Helpers.CommonFunctions.IsHttpSessionNull)
            { return; }

            lock (HttpContext.Current.Session)
            {
                if (value == null)
                {
                    try
                    {
                        if (HttpContext.Current.Session[key + Helpers.CommonFunctions.GetAppDomainMultiplexer()] != null)
                        {
                            HttpContext.Current.Session.Remove(key + Helpers.CommonFunctions.GetAppDomainMultiplexer());
                        }
                    }
                    catch
                    {
                    }
                }
                else
                {
                    HttpContext.Current.Session[key + Helpers.CommonFunctions.GetAppDomainMultiplexer()] = value;

                }
            }
        }
mjwills
  • 23,389
  • 6
  • 40
  • 63
  • Do you have any code that creates Tasks / Threads / Background Workers etc? – mjwills Jun 07 '17 at 13:18
  • Hello mjwills, I know, this object is still there (session state) from our project but it has been deleted by native asp.net session manager.(asp.net session object removed). The problem not reproducible local/live for environment. Only happening in is Prodcution environment. – Onur Dikmen Jun 07 '17 at 13:24
  • What makes you think that is the cause @ONURDİKMEN? Even if the session expires, you shouldn't get the exception you are seeing. The most common cause of that exception is multi-threaded access to Session objects. See https://stackoverflow.com/questions/24987909/is-session-variable-thread-safe-within-a-parallel-for-loop-in-asp-net-page . – mjwills Jun 07 '17 at 13:26
  • Are you able to confirm whether you have any code that creates Tasks / Threads / Background Workers etc? – mjwills Jun 07 '17 at 13:26
  • 1
    These kinds of issues (race conditions / multi-threaded issues) are always way more likely to occur in production, purely due to load (i.e. more users, more stuff executing). – mjwills Jun 07 '17 at 13:34
  • By the way session isn't thread safe.I have not seen any sync (lock, concurrent list etc) code in the source code. – Onur Dikmen Jun 07 '17 at 13:55
  • I use session as In-Proc mode and yes it contains lot of complex objects. – Onur Dikmen Jun 07 '17 at 13:56
  • Can you point me to any examples where you have Session being accessed inside a new Thread / Task? – mjwills Jun 07 '17 at 14:00
  • 1
    If a single web request results in multiple threads running and accessing the Session object, things will break. There is no way around it - it isn't designed to be thread-safe. I will add some code to consider using. – mjwills Jun 08 '17 at 06:46