I'm developing a C module with the help of SWIG. My library manages objects with reference counting, much like Python, except that it's deterministic: there's no GC. I'm using Python 3.5.2.
I create two Python objects like this: bakery = Bakery() bread = bakery.create_bread() Behind the scenes, the situation looks like this: +--------------------+ | UserBread obj (Py) | +----------^---+-----+ | : | : | : +------------------+ +---------+---V---+ | Bakery obj (lib) <----------------+ Bread obj (lib) | +--------^---+-----+ +--------^--------+ | : | | : | +--------+---V----+ +--------+-------+ | Bakery obj (Py) | | Bread obj (Py) | +---------^-------+ +------^---------+ | | | | + + bakery bread A pipe link means one "strong" reference and a colon link means one borrowed/weak reference. I have some ownership inversion magic for the Bakery lib. and Python objects to always coexist. So here it's pretty clear what can happen. I don't know which reference gets deleted first, but let's assume it's `bakery`. Then the situation looks like this: +--------------------+ | UserBread obj (Py) | +----------^---+-----+ | : | : | : +------------------+ +---------+---V---+ | Bakery obj (lib) <----------------+ Bread obj (lib) | +--------^---+-----+ +--------^--------+ : | | : | | +--------+---V----+ +--------+-------+ | Bakery obj (Py) | | Bread obj (Py) | +-----------------+ +------^---------+ | | + bread The Bakery Python object's __del__() drops the reference to its library object, but first its reference count is incremented during this call (so it's not really destroyed) and it's marked as only owned by the library object from now on. When `bread` gets deleted: 1. The Bread Python object's __del__() method gets called: the reference to its library object is dropped. 2. The Bread library object's destroy function drops its reference to the Bakery library object. 3. The Bakery library object's destroy function drops its reference to the Bakery Python object. 4. The Bakery Python object's __del__() method does nothing this time, since the object is marked as only owned by its library object (inverted ownership). 5. The Bread library object's destroy function then drops its reference to the UserBread Python object. In the end, everything is correctly destroyed and released. This also works if `bread` is deleted before `bakery`. My problem is that this works as expected when used like this: def func(): bakery = Bakery() bread = bakery.create_bread() if __name__ == '__main__': func() but NOTHING is destroyed when used like this: bakery = Bakery() bread = bakery.create_bread() That is, directly during the module's initialization. It works, however, if I delete `bread` manually: bakery = Bakery() bread = bakery.create_bread() del bread It also works with `bakery` only: bakery = Bakery() My question is: what could explain this? My guess is that my logic is correct since it works fine in the function call situation. It feels like `bread` is never deleted in the module initialization situation, but I don't know why: the only reference to the Bread Python object is this `bread` name in the module... what could prevent this object's __del__() method to be called? It works when I call `del bread` manually: I would expect that the module finalization does the exact same thing? Am I missing anything? Thanks, Phil -- https://mail.python.org/mailman/listinfo/python-list