Closed
Description
Crash report
What happened?
This is not a standalone reproducer as I'm still working on that, but the code triggering it is:
@classmethod
def _get_referred_objs(cls, obj, predicate=lambda x: True):
visited = set()
objs = []
def update_refs(obj):
obj_id = id(obj)
# Avoid cycles. Use the id() of the objects directly since the
# inclusion check is orders of magnitude faster than checking for
# inclusing on the object directly. It also handles well non hashable
# objects and broken __eq__ implementations.
if obj_id in visited:
return
else:
visited.add(obj_id)
# Filter-out weird objects that end up in the list and that can
# trigger a coredump on the interpreter
with warnings.catch_warnings():
warnings.simplefilter("ignore")
has_class = hasattr(obj, '__class__')
if has_class and predicate(obj):
objs.append(obj)
for sub in gc.get_referents(obj):
update_refs(sub)
update_refs(obj)
return objs
The issue was triggered on Gentoo on an arm64 machine. For some reason, this works fine on x86-64. I then managed to trigger it again under a different Python 3.12.4 interpreter compiled from the git repo with debug symbols to get a gdb backtrace:
#6 0x0000aaaaaadfd4a0 in _PyObject_AssertFailed (obj=obj@entry=<_asyncio.FutureIter at remote 0xfffff210b3d0>, expr=expr@entry=0x0,
msg=msg@entry=0xaaaaaaea5c50 "object has negative ref count", file=<optimized out>, line=<optimized out>,
function=function@entry=0xaaaaaaed4928 <__func__.44.lto_priv.1> "_Py_NegativeRefcount") at Objects/object.c:2603
#7 0x0000aaaaaadfd550 in _Py_NegativeRefcount (filename=<optimized out>, lineno=<optimized out>, op=op@entry=<_asyncio.FutureIter at remote 0xfffff210b3d0>) at Objects/object.c:209
#8 0x0000fffff5df4bb0 in Py_DECREF (filename=filename@entry=0xfffff5dfba58 "./Modules/_asynciomodule.c", lineno=lineno@entry=1764, op=<_asyncio.FutureIter at remote 0xfffff210b3d0>)
at ./Include/object.h:682
#9 0x0000fffff5df59a0 in FutureIter_clear (it=<optimized out>) at ./Modules/_asynciomodule.c:1764
#10 0x0000fffff5dfb57c in FutureIter_dealloc (it=0xfffff2109f50) at ./Modules/_asynciomodule.c:1601
#11 0x0000aaaaaabc9658 in _Py_Dealloc (op=op@entry=<_asyncio.FutureIter at remote 0xfffff2109f50>) at Objects/object.c:2625
#12 0x0000aaaaaabc9acc in Py_DECREF (filename=filename@entry=0xaaaaaae65f90 "./Include/object.h", lineno=lineno@entry=798, op=<_asyncio.FutureIter at remote 0xfffff2109f50>)
at ./Include/object.h:690
#13 0x0000aaaaaabc9a68 in Py_XDECREF (op=<optimized out>) at ./Include/object.h:798
#14 0x0000aaaaaabc9780 in list_dealloc (op=0xffffdd2bc5a0) at Objects/listobject.c:356
#15 0x0000aaaaaabc9658 in _Py_Dealloc (
The Python backtrace at this point was deeply recursed in update_refs()
.
CPython versions tested on:
3.12
Operating systems tested on:
Linux
Output from running 'python -VV' on the command line:
Python 3.12.4 (tags/v3.12.4:8e8a4baf652, Aug 2 2024, 18:22:31) [GCC 13.3.1 20240614]
Linked PRs
- [3.12] gh-122695: Fix double-free when using
gc.get_referents
with a freed_asyncio.FutureIter
#122834 - [3.13] gh-122695: Fix double-free when using
gc.get_referents
with a freed_asyncio.FutureIter
#122837 - [3.12] gh-122695: Fix double-free when using
gc.get_referents
with a freed_asyncio.FutureIter
(#122837) #122859
Metadata
Metadata
Assignees
Projects
Status
Done