File tree Expand file tree Collapse file tree 2 files changed +57
-0
lines changed Expand file tree Collapse file tree 2 files changed +57
-0
lines changed Original file line number Diff line number Diff line change @@ -1155,6 +1155,37 @@ def test_something(self):
1155
1155
""" )
1156
1156
assert_python_ok ("-c" , source )
1157
1157
1158
+ def test_do_not_cleanup_type_subclasses_before_finalization (self ):
1159
+ # See https://github.com/python/cpython/issues/135552
1160
+ # If we cleanup weakrefs for tp_subclasses before calling
1161
+ # the finalizer (__del__) then the line `fail = BaseNode.next.next`
1162
+ # should fail because we are trying to access a subclass
1163
+ # attribute. But subclass type cache was not properly invalidated.
1164
+ code = """
1165
+ class BaseNode:
1166
+ def __del__(self):
1167
+ BaseNode.next = BaseNode.next.next
1168
+ fail = BaseNode.next.next
1169
+
1170
+ class Node(BaseNode):
1171
+ pass
1172
+
1173
+ BaseNode.next = Node()
1174
+ BaseNode.next.next = Node()
1175
+ """
1176
+ # this test checks garbage collection while interp
1177
+ # finalization
1178
+ assert_python_ok ("-c" , textwrap .dedent (code ))
1179
+
1180
+ code_inside_function = textwrap .dedent (F"""
1181
+ def test():
1182
+ { textwrap .indent (code , ' ' )}
1183
+
1184
+ test()
1185
+ """ )
1186
+ # this test checks regular garbage collection
1187
+ assert_python_ok ("-c" , code_inside_function )
1188
+
1158
1189
1159
1190
class IncrementalGCTests (unittest .TestCase ):
1160
1191
@unittest .skipIf (_testinternalcapi is None , "requires _testinternalcapi" )
Original file line number Diff line number Diff line change @@ -1044,6 +1044,32 @@ def callback(obj):
1044
1044
stderr = res .err .decode ("ascii" , "backslashreplace" )
1045
1045
self .assertNotRegex (stderr , "_Py_Dealloc: Deallocator of type 'TestObj'" )
1046
1046
1047
+ def test_clearing_weakrefs_in_gc (self ):
1048
+ # This test checks that when finalizers are called:
1049
+ # 1. weakrefs with callbacks have been cleared
1050
+ # 2. weakrefs without callbacks have not been cleared
1051
+ errors = []
1052
+ def test ():
1053
+ class Class :
1054
+ def __init__ (self ):
1055
+ self ._self = self
1056
+ self .wr1 = weakref .ref (Class , lambda x : None )
1057
+ self .wr2 = weakref .ref (Class )
1058
+
1059
+ def __del__ (self ):
1060
+ # we can't use assert* here, because gc will swallow
1061
+ # exceptions
1062
+ if self .wr1 () is not None :
1063
+ errors .append ("weakref with callback as cleared" )
1064
+ if self .wr2 () is not Class :
1065
+ errors .append ("weakref without callback was cleared" )
1066
+
1067
+ Class ()
1068
+
1069
+ test ()
1070
+ gc .collect ()
1071
+ self .assertEqual (errors , [])
1072
+
1047
1073
1048
1074
class SubclassableWeakrefTestCase (TestBase ):
1049
1075
You can’t perform that action at this time.
0 commit comments