ets-labs/python-dependency-injector

Use of __self__ (possibly in conjunction with providers.Container) seems to cause memory leaks

Opened this issue · 0 comments

Here's a (pretty sloppy) sort of minimal reproduction, together with some investigation that I've been doing:

import gc
import time
import weakref

import objgraph
from dependency_injector import containers, providers


class Parent(containers.DeclarativeContainer):
    __self__ = providers.Self()
    config = providers.Configuration(default={})

    a_factory = providers.Factory(lambda container: True, __self__)


class Child(containers.DeclarativeContainer):
    a_parent = providers.Container(Parent)


def test_parent_container_allocation(testing_container):
    parent = Parent()
    count = 500
    for _ in range(count):
        Child(a_parent=parent)
    time.sleep(1)
    gc.collect()

    random_container = weakref.ref(objgraph.by_type("DynamicContainer"))
    print(objgraph.show_backrefs(random_container(), max_depth=20))
    chain = objgraph.find_backref_chain(random_container, objgraph.is_proper_module)
    import ipdb

    ipdb.set_trace()
    assert len(objgraph.by_type("DynamicContainer")) < 50