Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory leak when singleton in child container depend on singleton in parent via an interface #113

Closed
jo-hel opened this issue Oct 19, 2018 · 1 comment

Comments

@jo-hel
Copy link

jo-hel commented Oct 19, 2018

Description

There seem to be a memory leak if a singleton registered in a child container depend on a singleton in the parent container via an interface. See example.

Using parentContainer.RegisterType<IA, A>(new ContainerControlledLifetimeManager()); solves the memory issue, but causes IA and A to resolve to different objects.

I would have expected some way to register both IA and A so they resolve the same object, and that all objects in a child container to be released when that child container is disposed.

Discovered this problem when upgrading from 4.0.1 to 5.8.6, but 5.8.11 has the same problem.

To Reproduce

    public interface IA { }
    class A : IA { }
    class B 
    {
        public IA A { get; }
        public B(IA a)
        {
            A = a;
        }
    }

    class Program
    {
        
        static void Main(string[] args)
        {
            using (var parentContainer = new UnityContainer())
            {
                parentContainer.RegisterType<A>(new ContainerControlledLifetimeManager());
                parentContainer.RegisterType<IA, A>();
                using (var childContainer = parentContainer.CreateChildContainer())
                {

                    childContainer.RegisterSingleton< B>();
                    var b = childContainer.Resolve<B>();
                    Console.WriteLine("ia == a: " + (childContainer.Resolve<IA>() == childContainer.Resolve<A>()));
                }
                // B is kept alive by the parentContainer
                Console.WriteLine("Press any key"); 
                Console.ReadKey();
            }
        }
    }

Additional context

Creating a memory snapshot after the child container has been disposed reveals the B object still being alive. dotMemory reports the retention path as following:

Retention path of UnityMemoryLeak.B

Unity.UnityContainer._registrations ->
Unity.Storage.HashRegistry<System.Type, Unity.Storage.IRegistry<System.String, Unity.Policy.IPolicySet>>.Entries ->
Unity.Storage.HashRegistry+Entry<System.Type, Unity.Storage.IRegistry<System.String, Unity.Policy.IPolicySet>>[37] at [5].Value ->
Unity.Storage.LinkedRegistry.Value ->
Unity.Registration.ContainerRegistration.Next ->
Unity.Storage.LinkedNode<System.Type, Unity.Policy.IBuilderPolicy>.Value ->
Unity.ObjectBuilder.BuildPlan.DynamicMethod.DynamicMethodBuildPlan._buildMethod ->
Unity.ObjectBuilder.BuildPlan.DynamicMethod.DynamicBuildPlanMethod._target ->
Unity.Strategies.BuildKeyMappingStrategy+<>c__DisplayClass0_0.context ->
Unity.Builder.BuilderContext.k__BackingField ->
Unity.Builder.BuilderContext.k__BackingField ->
UnityMemoryLeak.B

@appel1
Copy link

appel1 commented Oct 25, 2018

This looks like the same issue as #86.

@ENikS ENikS closed this as completed in ee085a2 Dec 4, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants