Oh, I confirm that the bug occurs on Python 3.5.1+ (3.5 branch) and Python 3.6 (default branch).
Call stack: _Py_Dealloc() => subtype_dealloc() => PyObject_ClearWeakRefs() => handle_callback() of weakref => ... => gc_collect => ... => assertion error
Full gdb tracebacks:
python: Modules/gcmodule.c:364: update_refs: Assertion `((gc)->gc.gc_refs >> (1)) != 0' failed.
Program received signal SIGABRT, Aborted.
0x00007ffff7129a98 in raise () from /lib64/libc.so.6
(gdb) where
#0 0x00007ffff7129a98 in raise () from /lib64/libc.so.6
#1 0x00007ffff712b69a in abort () from /lib64/libc.so.6
#2 0x00007ffff7122227 in __assert_fail_base () from /lib64/libc.so.6
#3 0x00007ffff71222d2 in __assert_fail () from /lib64/libc.so.6
#4 0x0000000000441b74 in update_refs (containers=0x939c60 <generations+64>) at Modules/gcmodule.c:364
#5 0x0000000000442cb1 in collect (generation=2, n_collected=0x7fffffff87f0, n_uncollectable=0x7fffffff87e8, nofail=0) at Modules/gcmodule.c:950
#6 0x00000000004432dd in collect_with_callback (generation=2) at Modules/gcmodule.c:1119
#7 0x00000000004434cb in gc_collect (self=<module at remote 0x7ffff05e2a58>, args=(), kws=0x0) at Modules/gcmodule.c:1213
#8 0x00000000004d5731 in PyCFunction_Call (func=<built-in method collect of module object at remote 0x7ffff05e2a58>, args=(), kwds=0x0)
at Objects/methodobject.c:98
#9 0x00000000005d0fd3 in call_function (pp_stack=0x7fffffff8a18, oparg=0) at Python/ceval.c:4732
#10 0x00000000005c8cc0 in PyEval_EvalFrameEx (f=Frame 0x7ffff7eaa858, for file crash.py, line 7, in callback (o=<weakref at remote 0x7ffff05eb658>),
throwflag=0) at Python/ceval.c:3207
#11 0x00000000005ce4ec in _PyEval_EvalCodeWithName (_co=<code at remote 0x7ffff7e8f340>,
globals={'__package__': None, '__name__': '__main__', 'gc': <module at remote 0x7ffff05e2a58>, 'weakref': <module at remote 0x7ffff05cae58>, '__builtins__': <module at remote 0x7ffff7f5fc58>, 'C': <type at remote 0xac3978>, '__doc__': None, '__spec__': None, 'main': <function at remote 0x7ffff05c1788>, 'callback': <function at remote 0x7ffff05c1338>, '__loader__': <SourceFileLoader(name='__main__', path='crash.py') at remote 0x7ffff7e7de28>, '__file__': 'crash.py', '__cached__': None}, locals=0x0, args=0x7ffff05d5b78, argcount=1, kws=0x0, kwcount=0, defs=0x0, defcount=0, kwdefs=0x0, closure=0x0, name=0x0, qualname=0x0)
at Python/ceval.c:4045
#12 0x00000000005ce61e in PyEval_EvalCodeEx (_co=<code at remote 0x7ffff7e8f340>,
globals={'__package__': None, '__name__': '__main__', 'gc': <module at remote 0x7ffff05e2a58>, 'weakref': <module at remote 0x7ffff05cae58>, '__builtins__': <module at remote 0x7ffff7f5fc58>, 'C': <type at remote 0xac3978>, '__doc__': None, '__spec__': None, 'main': <function at remote 0x7ffff05c1788>, 'callback': <function at remote 0x7ffff05c1338>, '__loader__': <SourceFileLoader(name='__main__', path='crash.py') at remote 0x7ffff7e7de28>, '__file__': 'crash.py', '__cached__': None}, locals=0x0, args=0x7ffff05d5b78, argcount=1, kws=0x0, kwcount=0, defs=0x0, defcount=0, kwdefs=0x0, closure=0x0) at Python/ceval.c:4066
#13 0x0000000000688276 in function_call (func=<function at remote 0x7ffff05c1338>, arg=(<weakref at remote 0x7ffff05eb658>,), kw=0x0)
at Objects/funcobject.c:604
#14 0x000000000046c4f3 in PyObject_Call (func=<function at remote 0x7ffff05c1338>, arg=(<weakref at remote 0x7ffff05eb658>,), kw=0x0)
at Objects/abstract.c:2170
#15 0x000000000046d61d in PyObject_CallFunctionObjArgs (callable=<function at remote 0x7ffff05c1338>) at Objects/abstract.c:2450
#16 0x0000000000576063 in handle_callback (ref=0x7ffff05eb658, callback=<function at remote 0x7ffff05c1338>) at Objects/weakrefobject.c:868
#17 0x0000000000576257 in PyObject_ClearWeakRefs (object=<C at remote 0x7ffff05d5ae8>) at Objects/weakrefobject.c:913
#18 0x00000000004f3bee in subtype_dealloc (self=<C at remote 0x7ffff05d5ae8>) at Objects/typeobject.c:1162
#19 0x00000000004dd7d6 in _Py_Dealloc (op=<C at remote 0x7ffff05d5ae8>) at Objects/object.c:1783
(...)
(gdb) py-bt
Traceback (most recent call first):
Garbage-collecting
<built-in method collect of module object at remote 0x7ffff05e2a58>
File "crash.py", line 7, in callback
gc.collect()
File "crash.py", line 17, in main
del c
File "crash.py", line 20, in <module>
main()
|
so I just discovered that the object that has the zero refcount has the same tp_dealloc:
(gdb) print *FROM_GC(gc)->ob_type
$8 = {ob_base = {ob_base = {_ob_next = 0x7f80c8aafc88, _ob_prev = 0x7f80c8aafd00, ob_refcnt = 7, ob_type = 0x7f80cd8c86e0 <PyType_Type>}, ob_size = 0}, tp_name = 0x7f80c8aa5c38 "_GatheringFuture", tp_basicsize = 104, tp_itemsize = 0,
tp_dealloc = 0x7f80cd41bee7 <subtype_dealloc>, tp_print = 0x0, tp_getattr = 0x0, tp_setattr = 0x0, tp_as_async = 0x556ba4342d58, tp_repr = 0x7f80c8870a9b <FutureObj_repr>, tp_as_number = 0x556ba4342d70, tp_as_sequence = 0x556ba4342ea8,
tp_as_mapping = 0x556ba4342e90, tp_hash = 0x7f80cd54c995 <_Py_HashPointer>, tp_call = 0x0, tp_str = 0x7f80cd423d05 <object_str>, tp_getattro = 0x7f80cd3fec8b <PyObject_GenericGetAttr>, tp_setattro = 0x7f80cd3ff0b5 <PyObject_GenericSetAttr>,
tp_as_buffer = 0x556ba4342ef8, tp_flags = 808449, tp_doc = 0x7f80c8cd7380 "Helper for gather().\n\n This overrides cancel() to cancel all the children and act more\n like Task.cancel(), which doesn't immediately mark itself as\n cancelled.\n ",
tp_traverse = 0x7f80cd41baae <subtype_traverse>, tp_clear = 0x7f80cd41bd5c <subtype_clear>, tp_richcompare = 0x7f80cd423d42 <object_richcompare>, tp_weaklistoffset = 96, tp_iter = 0x7f80c8871d4f <future_new_iter>,
tp_iternext = 0x7f80cd3fe6d6 <_PyObject_NextNotImplemented>, tp_methods = 0x0, tp_members = 0x556ba4342f28, tp_getset = 0x0, tp_base = 0x7f80c8a7b3c0 <FutureType>, tp_dict = 0x7f80c8aafc88, tp_descr_get = 0x0, tp_descr_set = 0x0, tp_dictoffset = 88,
tp_init = 0x7f80cd431000 <slot_tp_init>, tp_alloc = 0x7f80cd41b7f8 <PyType_GenericAlloc>, tp_new = 0x7f80cd41b9c6 <PyType_GenericNew>, tp_free = 0x7f80cd583d8b <PyObject_GC_Del>, tp_is_gc = 0x0, tp_bases = 0x7f80c8ab20c0, tp_mro = 0x7f80c8aafd00,
tp_cache = 0x0, tp_subclasses = 0x0, tp_weaklist = 0x7f80c8aae5d8, tp_del = 0x0, tp_version_tag = 791, tp_finalize = 0x7f80c8870ddb <FutureObj_finalize>}
This is for a GatheringFuture, something tells me perhaps there is more to this function that needs to be resolved?
|