pdb files for SimpleInjector 2.5.0 - NET 4.0

Sep 13, 2014 at 12:13 AM
Hello,

I'm trying to troubleshoot a Stackoverflow exception I'm seeing when calling the container.Verify method. Where would I be able to find the pdb files for v2.5.0 (NET 4.0) of SimpleInjector?

Thank you,

Manuel
Coordinator
Sep 13, 2014 at 10:10 AM
Hi Manual,

I'm sorry you got this error. Stack overflow exceptions are really annoying and often hard to debug. We tried our best to prevent stack overflow exceptions from happening in Simple Injector, but it is possible that this one slipped through the cracks.

Unfortunately, the pdb files aren't available online. We thought about making pdbs available through SymbolSource, but we found the time for doing this.

Can you post a stacktrace and a configuration that reproduces the problem? Most likely the problem is caused by a cyclic reference in your configuration. Simple Injector should be able to spot this in almost all cases though. With more information provided, we will hopefully be able to tell you how to change your configuration.

We are very passionate about delivering good quality software and if this is a bug in Simple Injector, we'll do our best to fix it ASAP. So any information that would help reproducing this is very welcome.

Steven
Sep 15, 2014 at 5:35 PM
Hi Steven,

Thank you for your prompt reply. I tried to use dot net reflector to debug the simpleinjector assemblies but I wasn't successful. Here's what I see in my call stack when the exception happens:
SimpleInjector.Compiled!DynamicInstanceProducer184.GetInstance(object[] constants)  Unknown
SimpleInjector.dll!SimpleInjector.CompilationHelpers.CompileInDynamicAssemblyAsClosure<System.__Canon>.AnonymousMethod__1a()    Unknown
SimpleInjector.dll!SimpleInjector.InstanceProducer.GetInstance()    Unknown
SimpleInjector.dll!SimpleInjector.InstanceProducer.VerifyInstanceCreation() Unknown
SimpleInjector.dll!SimpleInjector.Container.VerifyInstanceCreation(SimpleInjector.InstanceProducer[] producersToVerify) Unknown
SimpleInjector.dll!SimpleInjector.Container.Verify()    Unknown

I'm not sure if I can easily provide you with a configuration that reproduces this issue unless I give you the entire source code of the project. We have a wcf service and the dependency graph for our business project is complex. I'm trying to track what changes have happened within the last month as I've confirmed that our version of the codebase a month ago wasn't having this StackOverflow exception.

I figured the easiest way to find what configuration is causing this exception would to be debug SimpleInjector but without the pdb files I can't do this. If you have any other tips for how I can debug this issue I'd appreciate it a lot.

Thanks again,

Manuel
Sep 15, 2014 at 5:37 PM
By the way, there's the exception I see: An unhandled exception of type 'System.StackOverflowException' occurred in SimpleInjector.Compiled

If I click on View Detail... I see the following:

System.StackOverflowException {Cannot evaluate expression because the current thread is in a stack overflow state.}
_HResult -2147023895
_message null
Sep 15, 2014 at 10:30 PM
Steven,

I got a dump of the stackoverflow exception here
Sep 15, 2014 at 10:37 PM
Steven,

Here's the call stack when the exception happens:

[[FaultingExceptionFrame]]
DynamicClass.lambda_method(System.Runtime.CompilerServices.Closure)+3e
SimpleInjector.InstanceProducer.GetInstance()+126
SimpleInjector.InstanceProducer.VerifyInstanceCreation()+4b
SimpleInjector.Container.VerifyInstanceCreation(SimpleInjector.InstanceProducer[])+10b
SimpleInjector.Container.VerifyThatAllRootObjectsCanBeCreated()+15d
SimpleInjector.Container.Verify()+88
EnterpriseBilling.Bootstrapper.Bootstrap()+124
EnterpriseBilling.Global.Application_Start(System.Object, System.EventArgs)+d9
[[DebuggerU2MCatchHandlerFrame]]
[[HelperMethodFrame_PROTECTOBJ] (System.RuntimeMethodHandle.InvokeMethod)] System.RuntimeMethodHandle.InvokeMethod(System.Object, System.Object[], System.Signature, Boolean)
mscorlib_ni!System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(System.Object, System.Object[], System.Object[])+4c
mscorlib_ni!System.Reflection.RuntimeMethodInfo.Invoke(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo)+c1
mscorlib_ni!System.Reflection.MethodBase.Invoke(System.Object, System.Object[])+23
System_Web_ni!System.Web.HttpApplication.InvokeMethodWithAssert(System.Reflection.MethodInfo, Int32, System.Object, System.EventArgs)+7d
System_Web_ni!System.Web.HttpApplication.ProcessSpecialRequest(System.Web.HttpContext, System.Reflection.MethodInfo, Int32, System.Object, System.EventArgs, System.Web.SessionState.HttpSessionState)+18f
System_Web_ni!System.Web.HttpApplicationFactory.EnsureAppStartCalledForIntegratedMode(System.Web.HttpContext, System.Web.HttpApplication)+1c5
System_Web_ni!System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr, System.Web.HttpContext, System.Reflection.MethodInfo[])+af
System_Web_ni!System.Web.HttpApplication.InitSpecial(System.Web.HttpApplicationState, System.Reflection.MethodInfo[], IntPtr, System.Web.HttpContext)+130
System_Web_ni!System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr, System.Web.HttpContext)+194
System_Web_ni!System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr)+1db
System_Web_ni!DomainNeutralILStubClass.IL_STUB_COMtoCLR(Int64)+17
[[ContextTransitionFrame]]
[[ComMethodFrame]]
Coordinator
Sep 15, 2014 at 10:46 PM
I'm afraid that the stacktrace doesn't help much. Simple Injector will compile down registrations to anonymous delegates and this can result in a bunch of anonymous method calls on the call stack. It becomes impossible to see on which type the loop happens. Here's an idea. Instead of calling container.Verify(), loop over the container manually and resolve each instance. This doesn't resolve the problem, but allows you to find out on which registration everything breaks. Here's an example:
foreach (var producer in container.GetCurrentRegistrations())
{
    Console.WriteLine(producer.ServiceType.FullName);
    producer.GetInstance();
}
The type that is written last before the exception is thrown is either causing the issue, or it depends directly/indirectly on the type that is causing the cyclic reference.
Coordinator
Sep 17, 2014 at 7:35 PM
Hi Manuel, did you have any luck with the suggested code snippet?
Coordinator
Sep 20, 2014 at 12:03 PM
Hi Manuel,

I like to note that we just published a new beta for Simple Injector 2.6 to NuGet. This release has improved cyclic dependency detection and chances are good that if you upgrade to this beta release Simple Injector will spot your cyclic dependency instead of letting the CLR throw a stack overflow exception.

Please let me know if that works for you.
Sep 23, 2014 at 4:22 PM
Hi Steve,

I'll give the newest 2.6 beta version a try and will let you know what I find. Thanks again for your help.
Sep 23, 2014 at 6:59 PM
Steve,

Good news: it looks like the stack overflow exception I was getting when calling the container.Verify() method went away in the beta 2.6 version of SimpleInjector.

Bad news: the container.Verify() method is taking about 2 minutes and 20 seconds to run. I pulled older versions of the codebase and these take about 30 seconds. This call runs during the Application_Start event in the Global.asax file so it only happens the first time a user hits the service endpoint.

I did notice that in the 2.6 beta version, the memory footprint of the w3wp.exe process for my service doesn't go beyond 600,000K. In the 2.5 version of SimpleInjector, the memory footprint goes over 1000,000K and then I'd get the StackOverflow error.

I noticed we're registering a total of 765 types. I'm positive that this problem has more to do with how badly we're managing our dependency graph. We have several classes in our codebase that have 10 dependencies. Also, we have the following throughout our codebase:
Class A -> Class B, Class C
Class B -> Class E, Class F
Class E -> Class C

Manuel
Coordinator
Sep 23, 2014 at 8:50 PM
Edited Oct 9, 2014 at 10:41 PM
Hi Manuel,

I've asked @qujck to do some testing using the latest beta on his configuration with over 3000 registrations (with lots of generic decorators applied) and he reports that it runs within 6 seconds. So I assume that there's something else happening in your case.

First of all, could the difference in time between the two versions be caused by the old version stopping after 20 seconds because the stackoverflow is thrown? In other words, if you fix the cyclic dependency (which should be easy since the newest beta will show you where it is), I bet the old version takes 140 seconds as well.

Second, verification times that are that long are probably caused by having constructors or initializers that do too much. Do note that your constructors should be simple and building your object graphs should be fast and reliable. So prevent having to go to the file system, database, or anything slow and unreliable during object graph construction, and move that to later points in time. There are many ways to do that, and it depends on the situation. If you need help with that, please ask a new question here on the forum.

Last, if -after those improvements- verification is still slow (verification is often much slower when the debugger is attached), you might want to move the call to Verify() out of the composition root and into a unit/integration test. Since unit tests don't run with the debugger attached, they will be much faster and you don't slow down application startup, while still having the safety net that Verfiy() provides.
Marked as answer by dot_NET_Junkie on 9/28/2014 at 4:01 AM