3.6.0a0 (de982d8b7b15)
#0 0x080e62a1 in _PyTrash_thread_destroy_chain () at Objects/object.c:2010
#1 0x080bf8b3 in frame_dealloc (f=f@entry=0x83f06e4) at Objects/frameobject.c:462
#2 0x080e3eef in _Py_Dealloc (op=op@entry=0x83f06e4) at Objects/object.c:1786
#3 0x081909c1 in fast_function (func=func@entry=0xb77f4154, pp_stack=pp_stack@entry=0xbfffe6ac, n=n@entry=0, na=na@entry=0, nk=nk@entry=0) at Python/ceval.c:4752
#4 0x0819102a in call_function (pp_stack=pp_stack@entry=0xbfffe6ac, oparg=oparg@entry=0) at Python/ceval.c:4677
#5 0x0818e1f7 in PyEval_EvalFrameEx (f=f@entry=0xb795f034, throwflag=throwflag@entry=0) at Python/ceval.c:3181
#6 0x081906e7 in _PyEval_EvalCodeWithName (_co=_co@entry=0xb77f00f8, globals=globals@entry=0xb798f734, locals=locals@entry=0xb798f734, args=args@entry=0x0,
argcount=argcount@entry=0, kws=kws@entry=0x0, kwcount=kwcount@entry=0, defs=defs@entry=0x0, defcount=defcount@entry=0, kwdefs=kwdefs@entry=0x0,
closure=closure@entry=0x0, name=name@entry=0x0, qualname=qualname@entry=0x0) at Python/ceval.c:3962
#7 0x0819080a in PyEval_EvalCodeEx (_co=_co@entry=0xb77f00f8, globals=globals@entry=0xb798f734, locals=locals@entry=0xb798f734, args=args@entry=0x0,
argcount=argcount@entry=0, kws=kws@entry=0x0, kwcount=kwcount@entry=0, defs=defs@entry=0x0, defcount=defcount@entry=0, kwdefs=kwdefs@entry=0x0,
closure=closure@entry=0x0) at Python/ceval.c:3983
#8 0x0819086d in PyEval_EvalCode (co=co@entry=0xb77f00f8, globals=globals@entry=0xb798f734, locals=locals@entry=0xb798f734) at Python/ceval.c:777
#9 0x08180503 in builtin_exec_impl (module=module@entry=0xb7a1e534, source=0xb77f00f8, globals=0xb798f734, locals=0xb798f734) at Python/bltinmodule.c:942
#10 0x08180688 in builtin_exec (module=module@entry=0xb7a1e534, args=args@entry=0xb78b784c) at Python/clinic/bltinmodule.c.h:275
#11 0x080e025c in PyCFunction_Call (func=func@entry=0xb7a1ecb4, args=args@entry=0xb78b784c, kwds=kwds@entry=0x0) at Objects/methodobject.c:109
#12 0x08190f18 in call_function (pp_stack=pp_stack@entry=0xbfffe97c, oparg=oparg@entry=2) at Python/ceval.c:4651
#13 0x0818e1f7 in PyEval_EvalFrameEx (f=f@entry=0xb79d4cac, throwflag=throwflag@entry=0) at Python/ceval.c:3181
#14 0x081906e7 in _PyEval_EvalCodeWithName (_co=0xb78b9028, globals=<optimized out>, locals=locals@entry=0x0, args=args@entry=0xb7a00e84, argcount=argcount@entry=5,
kws=kws@entry=0xb7a00e98, kwcount=kwcount@entry=0, defs=defs@entry=0xb78ba288, defcount=5, kwdefs=kwdefs@entry=0x0, closure=closure@entry=0x0,
name=name@entry=0xb78b83e8, qualname=qualname@entry=0xb78b83e8) at Python/ceval.c:3962
#15 0x08190a52 in fast_function (func=func@entry=0xb7925994, pp_stack=pp_stack@entry=0xbfffeb3c, n=n@entry=5, na=na@entry=5, nk=nk@entry=0) at Python/ceval.c:4760
#16 0x0819102a in call_function (pp_stack=pp_stack@entry=0xbfffeb3c, oparg=oparg@entry=5) at Python/ceval.c:4677
#17 0x0818e1f7 in PyEval_EvalFrameEx (f=f@entry=0xb7a00d1c, throwflag=throwflag@entry=0) at Python/ceval.c:3181
#18 0x081906e7 in _PyEval_EvalCodeWithName (_co=_co@entry=0xb78b9298, globals=globals@entry=0xb78b17dc, locals=locals@entry=0x0, args=args@entry=0xb79b83c8,
argcount=argcount@entry=2, kws=kws@entry=0x0, kwcount=kwcount@entry=0, defs=defs@entry=0xb78b7eb8, defcount=defcount@entry=1, kwdefs=kwdefs@entry=0x0,
closure=closure@entry=0x0, name=name@entry=0x0, qualname=qualname@entry=0x0) at Python/ceval.c:3962
#19 0x0819080a in PyEval_EvalCodeEx (_co=0xb78b9298, globals=globals@entry=0xb78b17dc, locals=locals@entry=0x0, args=args@entry=0xb79b83c8, argcount=2,
kws=kws@entry=0x0, kwcount=kwcount@entry=0, defs=defs@entry=0xb78b7eb8, defcount=defcount@entry=1, kwdefs=0x0, closure=0x0) at Python/ceval.c:3983
#20 0x0820be82 in function_call (func=0xb7841454, arg=0xb79b83b4, kw=0x0) at Objects/funcobject.c:632
#21 0x080939ce in PyObject_Call (func=func@entry=0xb7841454, arg=arg@entry=0xb79b83b4, kw=kw@entry=0x0) at Objects/abstract.c:2147
#22 0x0807614a in RunModule (modname=modname@entry=0x8330308 L"json.tool", set_argv0=set_argv0@entry=1) at Modules/main.c:208
#23 0x08076f56 in Py_Main (argc=argc@entry=5, argv=argv@entry=0x832f010) at Modules/main.c:709
#24 0x0805edb4 in main (argc=5, argv=0xbfffee84) at ./Programs/python.c:69
|
The following simplified code produces the crash:
from collections import OrderedDict
obj = []
for _ in range(33):
obj = OrderedDict(((None, obj),))
for _ in range(17):
obj = [obj]
print("Still alive, crash happens at interpreter finalization")
This crashes at the same line as in Serhiy’s backtrace. In _PyTrash_thread_destroy_chain(), Py_TYPE(op) is a bad pointer (0xdbdbdbdbdbdbdbdb); I have enabled --with-pydebug.
|
Left a comment about a minor English grammar problem.
The existing comment Serhiy mentioned was added way back in 2003 for Issue 668433. It appears to use the same underlying technique, reverting the nesting level before calling the base class dealloc. One paragraph talks about the extra increment used there compared to Serhiy’s method:
'''
But now it's possible that a chain of objects consisting solely of objects whose deallocator is subtype_dealloc() will defeat the trashcan mechanism completely: the decremented level means that the effective level never reaches the limit. Therefore, we *increment* the level *before* entering the trashcan block, and matchingly decrement it after leaving. This means the trashcan code will trigger a little early, but that's no big deal.
'''
I think we may not have to worry about this for ordered dict, assuming that PyDict_Type.tp_dealloc() can only recursively invoke odict_dealloc() from within its own trashcan block.
So as far as I can tell, this patch is good to apply, unless someone with more knowledge of garbage collection has any comments.
|