RequestContext.Items is not cleared sometimes on mono

Hi,

code:

        var appHost = HostContext.AppHost;
        appHost.PreRequestFilters.Insert(0, (req, res) =>
        {
            var adr = req.AbsoluteUri;
            _logger.Trace($"DEBUG - Adding RequestContext - {adr}");
            if (HostContext.RequestContext.Items.Contains(RequestObjectKey))
            {
                var oldr = HostContext.RequestContext.Items[RequestObjectKey] as IRequest;
                _logger.Trace($"DEBUG - RequestObject already exists in RequestContext. Old route: {oldr?.AbsoluteUri}, New route: {adr}");
            }
            HostContext.RequestContext.Items.Add(RequestObjectKey, req);
            _logger.Trace($"DEBUG - Added - {adr}");
        });

Log contents:

2016-10-06 13:46:31.4876|DEBUG|AppSelfHostBase|127.0.0.1:8889 Request : /egib/dzialki/1754
2016-10-06 13:46:31.4884|TRACE|GlobalLogger|DEBUG - Adding RequestContext - http://127.0.0.1:8889/egib/dzialki/1754
2016-10-06 13:46:31.4884|TRACE|GlobalLogger|DEBUG - RequestObject already exists in RequestContext. Old route: http://127.0.0.1:8889/egib/dzialki/1696, New route: http://127.0.0.1:8889/egib/dzialki/1754
2016-10-06 13:46:31.4884|ERROR|ServiceStackHost|Error occured while Processing Request: The key already existed in the dictionary.
2016-10-06 13:46:31.4894|ERROR|GlobalLogger| - IDENTYFIKATOR: 6/10/5143549 -  Adres: http://127.0.0.1:8889/egib/dzialki/1754 ; Wyjątek nie został obsłużony przez usługę - Wystąpił błąd serwera. Numer referencyjny: 6/10/5143549
0: The key already existed in the dictionary.
  at System.Collections.Concurrent.ConcurrentDictionary`2[TKey,TValue].System.Collections.Generic.IDictionary.Add (System.Collections.Concurrent.TKey key, System.Collections.Concurrent.TValue value) <0x412d5e90 + 0x00067> in :0
  at System.Collections.Concurrent.ConcurrentDictionary`2[TKey,TValue].System.Collections.IDictionary.Add (System.Object key, System.Object value) <0x412d5cb0 + 0x0010e> in :0
  at Perun.Host.Configuration.RequestToRequestContextRequestFilterConfigurator.b__3_0 (IRequest req, IResponse res) <0x412d5590 + 0x0023c> in :0
  at ServiceStack.ServiceStackHost.ApplyPreRequestFilters (IRequest httpReq, IResponse httpRes) <0x412d00a0 + 0x000a3> in :0
  at ServiceStack.Host.RestHandler.ProcessRequestAsync (IRequest httpReq, IResponse httpRes, System.String operationName) <0x412cf6a0 + 0x00210> in :0

ServiceStack version: 4.5.0.0

Primarily appeared on mono 4.4.2, we have upgraded our deployment servers to 4.6.1 but still exists. Tried to reproduce on Windows machines (running .NET), but it looks like it is mono only.

Hard to find on dev machines, but also exists. To reproduce:

  1. Send as many requests as possible. It takes above 1k requests for first exception.
  2. After first exception it happens more often, only server restart resets it.

Note that old request value had URI: http://127.0.0.1:8889/egib/dzialki/1696

Every next exception has same old uri. (Test was querying from 1-n). Sometimes time span between old uri call and new uri call can be few minutes!

I have added code that checks if key exist, but I guess this is not a solution.

Tomasz

Unfortunately RequestContext is dependent on correct behavior of the ASP.NET Host HttpContext.Current.Items and CallContext to work which Mono has historically had issues with. This sounds like a race condition bug in Mono’s impl. If you’re using a self-host and you’re not using async Services you can switch to use ThreadStatic instead of CallContext with:

RequestContext.UseThreadStatic = true;

There’s no workaround if this is happening in an ASP.NET host other than to avoid using RequestContext and Request Scoped dependencies. Long term the solution would be to get off Mono which will be available soon with our upcoming .NET Core support.

We are using self-host, and not using async services.
Where should I put this code? Does it need to be changed for every request in request filter?

Just once in AppHost.Configure().