gh-126312: Don't traverse frozen objects on the free-threaded build (#126338)

Also, _PyGC_Freeze() no longer freezes unreachable objects.

Co-authored-by: Sergey B Kirpichev <skirpichev@gmail.com>
This commit is contained in:
Peter Bierma 2024-11-15 05:21:30 -05:00 committed by GitHub
parent 8717f792f7
commit d4c72fed8c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 54 additions and 5 deletions

View file

@ -1082,6 +1082,44 @@ class GCTests(unittest.TestCase):
gc.collect()
self.assertTrue(collected)
def test_traverse_frozen_objects(self):
# See GH-126312: Objects that were not frozen could traverse over
# a frozen object on the free-threaded build, which would cause
# a negative reference count.
x = [1, 2, 3]
gc.freeze()
y = [x]
y.append(y)
del y
gc.collect()
gc.unfreeze()
def test_deferred_refcount_frozen(self):
# Also from GH-126312: objects that use deferred reference counting
# weren't ignored if they were frozen. Unfortunately, it's pretty
# difficult to come up with a case that triggers this.
#
# Calling gc.collect() while the garbage collector is frozen doesn't
# trigger this normally, but it *does* if it's inside unittest for whatever
# reason. We can't call unittest from inside a test, so it has to be
# in a subprocess.
source = textwrap.dedent("""
import gc
import unittest
class Test(unittest.TestCase):
def test_something(self):
gc.freeze()
gc.collect()
gc.unfreeze()
if __name__ == "__main__":
unittest.main()
""")
assert_python_ok("-c", source)
class IncrementalGCTests(unittest.TestCase):