Repository navigation
PyObject_ClearManagedDict() loses the propagating exception on MemoryError #159283
Description
Crash report
When an object whose __dict__ has been materialized, but still points at the object's inline values, is freed while an exception is propagating, and the allocation in detach_dict_from_object() fails, the propagating exception is lost.
PyObject_ClearManagedDict() in Objects/dictobject.c calls detach_dict_from_object(), which calls PyErr_NoMemory() when copy_values() fails. That replaces the exception in flight, and the PyErr_FormatUnraisable() call that follows clears it. A debug build aborts, and a release build carries on with no exception set, which ends in SystemError.
import _testcapi
class A:
pass
def make():
a = A()
a.x = 1
a.__dict__ # materialize a dict that still points at the inline values
return a
def f(holder, start):
_testcapi.set_nomemory(start, start + 1)
# The A instance is only referenced from the evaluation stack,
# so it is freed while ZeroDivisionError propagates.
[holder.pop(), 1/0]
for start in range(20):
try:
f([make()], start)
except (ZeroDivisionError, MemoryError):
pass
except BaseException as exc:
_testcapi.remove_mem_hooks()
print(start, repr(exc))
finally:
_testcapi.remove_mem_hooks()On main (64018ac) built with --with-pydebug:
Fatal Python error: py_dealloc: Deallocator of type 'A' cleared the current exception
In a release build of the same commit, one iteration gets SystemError instead of ZeroDivisionError:
Exception ignored while clearing an object managed dict:
Traceback (most recent call last):
File "repro.py", line 16, in f
[holder.pop(), 1/0]
~^~
MemoryError
4 SystemError('error return without exception set')
The same code is in 3.14 and 3.15. This is not the same problem as gh-152254, which is about the ownership assertion in the fallback that clears the dict.
Saving the current exception before detaching the dict and restoring it afterwards fixes both builds. I have a patch.
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Output from running 'python -VV' on the command line:
Python 3.16.0a0 (remotes/upstream/main:64018ac45cb, Oct 12 2026, 23:09:28) [GCC 13.3.0]
Activity