Open mdickinson opened 11 years ago
The problem seems to be that when the trait synchronization is set up (in https://github.com/enthought/traits/blob/master/traits/has_traits.py#L2652), the weakref callback is a member function (it doesn't matter whether the callback is a member of the object itself, or of the object to be synched with, but the former produces slightly nicer-looking cycles). See e.g. the following snippet:
import gc
import weakref
import refcycle
class A(object):
def baby_sync(self, obj, mutual=True):
self.ref = weakref.ref(obj, obj.callback)
if mutual:
obj.baby_sync(self, mutual=False)
def callback(self, ref):
pass
def create_cycles():
a = A()
b = A()
a.baby_sync(b)
def main():
gc.disable()
gc.collect()
create_cycles()
garbage = refcycle.garbage()
print "garbage: ", garbage
with open('garbage.gv', 'w') as f:
f.write(garbage.to_dot())
if __name__ == '__main__':
main()
The
sync_traits
method onHasTraits
objects creates reference cycles. In the script below, thecreate_cycles
function creates two cycles that won't get collected until the cyclic garbage collector runs. See the attached image for the details of the cycles.