Guido: > Well, it *also* abuses the ob_refcnt field. My patch fixes that too (by abusing the gc_prev pointer to chain trash together). > How about this wild idea (which Tim & I had simultaneously > yesterday): change the trashcan code to simply leave the > object in the GC generational list, and let the GC code > special-case objects with zero refcnt so that they are > eventually properly disposed? That could probably work. What happens when the GC is disabled? There is insidious bug here. Andrew helped me walk through it and I think we figured it out. First here's the code to trigger it: import gc class Ouch: def __del__(self): for x in range(20): list([]) def f(): gc.set_threshold(5) while 1: t = () # <-- here for i in range(300): t = [t, Ouch()] f() The line marked with "here" is where things go wrong. t used to refer to a long chain of [t, Ouch()]. The SETLOCAL macro in ceval calls Py_XDECREF(GETLOCAL(i)). That starts the deallocation of the list structure. Ouch.__del__ gets called can creates some more objects, triggering a collection. The f frame's traverse gets called and tries to follow the pointer for the t local. It points to memory that was freed by _PyTrash_destroy_chain. Hmm, now that I think about it the GC is not needed to trigger the bug: import gc gc.disable() import sys class Ouch: def __del__(self): print f_frame.f_locals['t'] def f(): global f_frame f_frame = sys._getframe() while 1: t = () for i in range(300): t = [t, Ouch()] f() I haven't figured out the correct solution yet. I'm just giving a status update. :-) Neil
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4