io.StringIO does not clear its reference to its attributes dictionary when deleted. This causes a leak when io.StringIO has attributes. >>> def leak(): ... for _ in range(100): ... f = io.StringIO() ... f.foo = 1 ... [39348 refs] >>> leak() [39650 refs] >>> leak() [39950 refs] >>> leak() [40250 refs]
It seems wrong to call PyObject_ClearWeakRefs() in stringio_clear(). Weakrefs should only be notified when the object is deallocated, not cleared. Besides, you should add a test for this, so that the leak can be spotted with regrtest -R.
Here's an updated patch. The new patch also cleans up tp_clear, tp_traverse and tp_dealloc of io.BytesIO which used weakreflist incorrectly. I also added support for test_memoryio for adding reference leak regression tests. As you'll see, the support is a bit heavyweight for the only test case there. So perhaps I could change this to something simpler.
Why do you need all this? Isn't it enough to take a weakref and check the callback is triggered? (besides, we should avoid tests which only work in debug mode)
> Why do you need all this? Isn't it enough to take a weakref and check > the callback is triggered? No, because you would need a weak reference to the instance's __dict__, which is unavailable for io.StringIO. Anyway, here's a simplified patch without the fun experimental code. :-)
I just noticed that this hadn't been committed to trunk. I did the backport myself, but in the future please first commit IO changes to trunk and then merge to py3k.