dadhi / DryIoc

DryIoc is fast, small, full-featured IoC Container for .NET
MIT License
1.03k stars 122 forks source link

Original stack trace is lost at Interpreter.TryInterpretAndUnwrapContainerException #250

Open ryoasai opened 4 years ago

ryoasai commented 4 years ago

I had a trouble while debugging a thread safety problem of my code.

When executing all test cases, one of my test case failed with the following exception:

System.NullReferenceException : Object reference not set to an instance of an object.
   at DryIoc.Interpreter.TryInterpretAndUnwrapContainerException(IResolverContext r, Expression expr, Boolean useFec, Object& result) in C:\projects\dryioc-qt8fa\src\DryIoc\Container.cs:line 2709
   at DryIoc.Factory.ApplyReuse(Expression serviceExpr, Request request) in C:\projects\dryioc-qt8fa\src\DryIoc\Container.cs:line 9484
   at DryIoc.Factory.GetExpressionOrDefault(Request request) in C:\projects\dryioc-qt8fa\src\DryIoc\Container.cs:line 9440
   at DryIoc.Container.ResolveAndCache(Int32 serviceTypeHash, Type serviceType, IfUnresolved ifUnresolved) in C:\projects\dryioc-qt8fa\src\DryIoc\Container.cs:line 388
   at DryIoc.Container.DryIoc.IResolver.Resolve(Type serviceType, IfUnresolved ifUnresolved) in C:\projects\dryioc-qt8fa\src\DryIoc\Container.cs:line 353
   at DryIoc.Resolver.Resolve(IResolver resolver, Type serviceType) in C:\projects\dryioc-qt8fa\src\DryIoc\Container.cs:line 7325
   at Prism.DryIoc.Ioc.DryIocContainerExtension.Resolve(Type type)
   at Prism.Ioc.IContainerProviderExtensions.Resolve[T](IContainerProvider provider)

But when I execute the failed test case, it somehow passed.

At first I had a fooled impression that the problem is in DryIoc code, but after digging into the problem, I found the NullRefereneException was thrown in Dictionary class. It was my fault that I was using the plain Dictionary class as a cache. Replacing it with CuncurrentDictionary solved the problem.

That's ok but a annoyingly that the original exception stack trace is lost at the following code:

          public static bool TryInterpretAndUnwrapContainerException(
            IResolverContext r, Expression expr, bool useFec, out object result)
        {
            try
            {
                return Interpreter.TryInterpret(r, expr, FactoryDelegateCompiler.ResolverContextParamExpr, r, null, useFec, out result);
            }
            catch (TargetInvocationException tex) when (tex.InnerException != null)
            {
                // restore the original excpetion which is expected by the consumer code
                throw tex.InnerException; // Original stack trace is lost here, make it hard to debug.
            }
        }

So it's not a DryIoC's bug per se but I think it's better that it will report the original stack trace to help debugging.

There seems to be a technique to keep the original stack trace, for example:

[https://stackoverflow.com/questions/57383/how-to-rethrow-innerexception-without-losing-stack-trace-in-c]()

Can you take a look at this problem? I'm currently using v4.1.3.

dadhi commented 4 years ago

@ryoasai This is a good catch! I will add the fix into the next minor version.

raV720 commented 1 week ago

I have the same issue on MAUI when simply calling: Resolve(). The stack trace:

   at DryIoc.Interpreter.TryInterpretSingletonAndUnwrapContainerException(IResolverContext r, Expression expr, ImMapEntry`1 itemRef, Object& result)
   at DryIoc.Factory.ApplyReuse(Expression serviceExpr, Request request)
   at DryIoc.Factory.GetExpressionOrDefault(Request request)
   at DryIoc.Container.ResolveAndCache(Int32 serviceTypeHash, Type serviceType, IfUnresolved ifUnresolved)
   at DryIoc.Container.DryIoc.IResolver.Resolve(Type serviceType, IfUnresolved ifUnresolved)
   at DryIoc.Resolver.Resolve[TService](IResolver resolver, IfUnresolved ifUnresolved)

The service is registred like: container.Register<IStartupService, StartupService>(reuse: Reuse.Singleton); The exception is thrown just inside ctor of StartupService. DryIoc.dll version: 5.4.3 DryIoc.Microsoft.DependencyInjection version: 6.2.0

raV720 commented 16 hours ago

@dadhi can you take a look at this problem?

dadhi commented 16 hours ago

@raV720 Can you check the latest preview versions of the DryIoc.Microsoft.DependencyInjection and DryIoc.dll?