MVC Mini-Profiler throws a LockRecursionException when changing RouteCollection

I see a pretty crazy mistake when using MVC MiniProfiler . With interruptions, the site I'm working on enters a state in which every request causes this exception to be thrown:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.TypeInitializationException: The type initializer for 'MvcMiniProfiler.MiniProfiler' threw an exception. ---> System.Threading.LockRecursionException: Write lock may not be acquired with read lock held. This pattern is prone to deadlocks. Please ensure that read locks are released before taking a write lock. If an upgrade is necessary, use an upgrade lock in place of the read lock. at System.Threading.ReaderWriterLockSlim.TryEnterWriteLockCore(Int32 millisecondsTimeout) at System.Threading.ReaderWriterLockSlim.TryEnterWriteLock(Int32 millisecondsTimeout) at System.Web.Routing.RouteCollection.GetWriteLock() at MvcMiniProfiler.UI.MiniProfilerHandler.RegisterRoutes() in C:\Users\sam\Desktop\mvc-mini-profiler\MvcMiniProfiler\UI\MiniProfilerHandler.cs:line 81 at MvcMiniProfiler.MiniProfiler..cctor() in C:\Users\sam\Desktop\mvc-mini-profiler\MvcMiniProfiler\MiniProfiler.cs:line 241 β€” End of inner exception stack trace β€” at MvcMiniProfiler.MiniProfiler.get_Current() at TotallyNotOverDrive.Boom.MvcApplication.Application_EndRequest() 

The error persists until the application pool is reused. It seems that some kind of lock is blocked, which prevents MiniProfiler from trying to register its routes. This happens for queries where I do not start MiniProfiler, but during Application_EndRequest I call MiniProfiler.Stop() , which seems to cause MiniProfiler to be created when accessing the current property. For a simple solution, I modified EndRequest to use the same logic to stop the profiler as BeginRequest, so if the request does not use the profiler, this error should be completely eliminated. I would still like to solve the real problem before sending this code to production.

My route table is pretty simple and only added to the Application_Start method. We do not use any other third-party code that can change the route table after launch. The only suspicious thing I did with routing was to add a custom route to the table, but this is a pretty simple route, I just needed to find a more complex template than the standard MVC route could do.

I looked at the corresponding MiniProfiler code and don’t see anything that could have caused the lock to not be released, so I assume that it combines with ASP.NET and MiniProfiler conflicts when accessing RouteTable. I cannot reliably reproduce the problem, so I am wondering if anyone else has such routing problems. Thanks for any help you can offer.

+7
source share
1 answer

I think I see what is happening, you need to get the routes registered earlier. You register them during EndRequest , at this moment there may be other requests in the pipeline that store read locks in the route table.

Routes are registered in the MiniProfiler static constructor. If you select any of the options in MiniProfiler during Application_Start , this will launch a static constructor that will register routes.

For example, try adding something like this right after registering your routes.

MiniProfiler.Settings.PopupMaxTracesToShow = 10;

+1
source

All Articles