Memory leak when ffi.callback() is in a reference cycle
CPython’s cycle collector does not seem to know about the reference held by
ffi.callback() objects to their function argument, which can cause memory leaks when a cycle goes through that reference.
I don’t know if PyPy is affected, leaks are not as easy to spot without
This test case fails on CPython with CFFI 0.6:
import gc import sys import cffi def make_callback(): container = [data] callback = ffi.callback('int()', lambda: len(vars(container))) container.append(callback) # Ref cycle: callback -> lambda (closure) -> container -> callback return callback ffi = cffi.FFI() data = 'something' initial_refcount = sys.getrefcount(data) callback = make_callback() assert sys.getrefcount(data) == initial_refcount + 1 del callback gc.collect() assert sys.getrefcount(data) == initial_refcount # Fails, data is leaked
An example of real code with this kind of cycle: https://github.com/SimonSapin/cairocffi/blob/v0.5/cairocffi/surfaces.py#L70
The issue can be worked around with weakref (which cairocffi will do), but it would be better fixed in CFFI.
http://docs.python.org/2/c-api/typeobj.html#PyTypeObject.tp_traverse seems to be related, but I’m not sure.