Setup
Running on latest immutable-main:
from immutable import freeze
class A:
pass
class Restart:
def __pre_freeze__(self):
freeze(self)
a = A()
a.l = [a, Restart()]
l = a.l # create another reference
freeze(A)
print("All good")
freeze(a)
Output
All good
./Include/refcount.h:673: _Py_NegativeRefcount: Assertion failed: object has negative ref count
<object at 0x73d90168be40 is freed>
Fatal Python error: _PyObject_AssertFailed: _PyObject_AssertFailed
Python runtime state: initialized
Current thread 0x000073d902611740 [python] (most recent call first):
File "/home/david/coding/cpython/personal/debug.py", line 8 in __pre_freeze__
File "/home/david/coding/cpython/personal/debug.py", line 15 in <module>
Aborted (core dumped)
What happens
When the freezing algorithms encounters a again, it creates an SCC but does not complete it yet, meaning that reference counts stay mostly intact.
The pre-freeze hook causes a restart, which unfreezes a, calling scc_reset_root_refcount.
However, that function assumes that the SCC already uses a single reference count in its representative.
Setup
Running on latest
immutable-main:Output
What happens
When the freezing algorithms encounters
aagain, it creates an SCC but does not complete it yet, meaning that reference counts stay mostly intact.The pre-freeze hook causes a restart, which unfreezes
a, callingscc_reset_root_refcount.However, that function assumes that the SCC already uses a single reference count in its representative.