blob: c0d4a7507ae0d381d56bec6180ad1fb09ba882c0 [file] [log] [blame]
Guido van Rossumd8faa362007-04-27 19:54:29 +00001import unittest
Neil Schemenauer392a13b2019-10-15 20:56:48 -07002import unittest.mock
Brett Cannon7a540732011-02-22 03:04:06 +00003from test.support import (verbose, refcount_test, run_unittest,
Victor Stinner6cac1132019-12-08 08:38:16 +01004 cpython_only, start_threads,
Victor Stinner626bff82018-10-25 17:31:10 +02005 temp_dir, requires_type_collecting, TESTFN, unlink,
6 import_module)
Berker Peksagce643912015-05-06 06:33:17 +03007from test.support.script_helper import assert_python_ok, make_script
Antoine Pitrou5f454a02013-05-06 21:15:57 +02008
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +00009import gc
Victor Stinner626bff82018-10-25 17:31:10 +020010import sys
11import sysconfig
12import textwrap
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020013import threading
Victor Stinner626bff82018-10-25 17:31:10 +020014import time
15import weakref
Antoine Pitrou2b0218a2012-09-06 00:59:49 +020016
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020017try:
18 from _testcapi import with_tp_del
19except ImportError:
20 def with_tp_del(cls):
21 class C(object):
22 def __new__(cls, *args, **kwargs):
23 raise TypeError('requires _testcapi.with_tp_del')
24 return C
25
Neil Schemenauer392a13b2019-10-15 20:56:48 -070026try:
27 from _testcapi import ContainerNoGC
28except ImportError:
29 ContainerNoGC = None
30
Guido van Rossumd8faa362007-04-27 19:54:29 +000031### Support code
32###############################################################################
Tim Peters0f81ab62003-04-08 16:39:48 +000033
Tim Petersead8b7a2004-10-30 23:09:22 +000034# Bug 1055820 has several tests of longstanding bugs involving weakrefs and
35# cyclic gc.
36
37# An instance of C1055820 has a self-loop, so becomes cyclic trash when
38# unreachable.
39class C1055820(object):
40 def __init__(self, i):
41 self.i = i
42 self.loop = self
43
44class GC_Detector(object):
45 # Create an instance I. Then gc hasn't happened again so long as
46 # I.gc_happened is false.
47
48 def __init__(self):
49 self.gc_happened = False
50
51 def it_happened(ignored):
52 self.gc_happened = True
53
54 # Create a piece of cyclic trash that triggers it_happened when
55 # gc collects it.
56 self.wr = weakref.ref(C1055820(666), it_happened)
57
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020058@with_tp_del
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +000059class Uncollectable(object):
60 """Create a reference cycle with multiple __del__ methods.
61
62 An object in a reference cycle will never have zero references,
63 and so must be garbage collected. If one or more objects in the
64 cycle have __del__ methods, the gc refuses to guess an order,
65 and leaves the cycle uncollected."""
66 def __init__(self, partner=None):
67 if partner is None:
68 self.partner = Uncollectable(partner=self)
69 else:
70 self.partner = partner
Antoine Pitrou796564c2013-07-30 19:59:21 +020071 def __tp_del__(self):
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +000072 pass
Tim Petersead8b7a2004-10-30 23:09:22 +000073
Victor Stinner626bff82018-10-25 17:31:10 +020074if sysconfig.get_config_vars().get('PY_CFLAGS', ''):
75 BUILD_WITH_NDEBUG = ('-DNDEBUG' in sysconfig.get_config_vars()['PY_CFLAGS'])
76else:
77 # Usually, sys.gettotalrefcount() is only present if Python has been
78 # compiled in debug mode. If it's missing, expect that Python has
79 # been released in release mode: with NDEBUG defined.
80 BUILD_WITH_NDEBUG = (not hasattr(sys, 'gettotalrefcount'))
81
Guido van Rossumd8faa362007-04-27 19:54:29 +000082### Tests
83###############################################################################
Tim Petersead8b7a2004-10-30 23:09:22 +000084
Guido van Rossumd8faa362007-04-27 19:54:29 +000085class GCTests(unittest.TestCase):
86 def test_list(self):
87 l = []
88 l.append(l)
89 gc.collect()
90 del l
91 self.assertEqual(gc.collect(), 1)
Tim Petersead8b7a2004-10-30 23:09:22 +000092
Guido van Rossumd8faa362007-04-27 19:54:29 +000093 def test_dict(self):
94 d = {}
95 d[1] = d
96 gc.collect()
97 del d
98 self.assertEqual(gc.collect(), 1)
Tim Petersead8b7a2004-10-30 23:09:22 +000099
Guido van Rossumd8faa362007-04-27 19:54:29 +0000100 def test_tuple(self):
101 # since tuples are immutable we close the loop with a list
102 l = []
103 t = (l,)
104 l.append(t)
105 gc.collect()
106 del t
107 del l
108 self.assertEqual(gc.collect(), 2)
Tim Petersead8b7a2004-10-30 23:09:22 +0000109
Guido van Rossumd8faa362007-04-27 19:54:29 +0000110 def test_class(self):
111 class A:
112 pass
113 A.a = A
114 gc.collect()
115 del A
116 self.assertNotEqual(gc.collect(), 0)
Tim Petersead8b7a2004-10-30 23:09:22 +0000117
Guido van Rossumd8faa362007-04-27 19:54:29 +0000118 def test_newstyleclass(self):
119 class A(object):
120 pass
121 gc.collect()
122 del A
123 self.assertNotEqual(gc.collect(), 0)
Tim Petersead8b7a2004-10-30 23:09:22 +0000124
Guido van Rossumd8faa362007-04-27 19:54:29 +0000125 def test_instance(self):
126 class A:
127 pass
128 a = A()
129 a.a = a
130 gc.collect()
131 del a
132 self.assertNotEqual(gc.collect(), 0)
Tim Petersead8b7a2004-10-30 23:09:22 +0000133
Serhiy Storchakaa7930372016-07-03 22:27:26 +0300134 @requires_type_collecting
Guido van Rossumd8faa362007-04-27 19:54:29 +0000135 def test_newinstance(self):
136 class A(object):
137 pass
138 a = A()
139 a.a = a
140 gc.collect()
141 del a
142 self.assertNotEqual(gc.collect(), 0)
143 class B(list):
144 pass
145 class C(B, A):
146 pass
147 a = C()
148 a.a = a
149 gc.collect()
150 del a
151 self.assertNotEqual(gc.collect(), 0)
152 del B, C
153 self.assertNotEqual(gc.collect(), 0)
154 A.a = A()
155 del A
156 self.assertNotEqual(gc.collect(), 0)
157 self.assertEqual(gc.collect(), 0)
Tim Petersead8b7a2004-10-30 23:09:22 +0000158
Guido van Rossumd8faa362007-04-27 19:54:29 +0000159 def test_method(self):
160 # Tricky: self.__init__ is a bound method, it references the instance.
161 class A:
162 def __init__(self):
163 self.init = self.__init__
164 a = A()
165 gc.collect()
166 del a
167 self.assertNotEqual(gc.collect(), 0)
Tim Petersead8b7a2004-10-30 23:09:22 +0000168
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200169 @cpython_only
Antoine Pitrou796564c2013-07-30 19:59:21 +0200170 def test_legacy_finalizer(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000171 # A() is uncollectable if it is part of a cycle, make sure it shows up
172 # in gc.garbage.
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200173 @with_tp_del
Guido van Rossumd8faa362007-04-27 19:54:29 +0000174 class A:
Antoine Pitrou796564c2013-07-30 19:59:21 +0200175 def __tp_del__(self): pass
Guido van Rossumd8faa362007-04-27 19:54:29 +0000176 class B:
177 pass
178 a = A()
179 a.a = a
180 id_a = id(a)
181 b = B()
182 b.b = b
183 gc.collect()
184 del a
185 del b
186 self.assertNotEqual(gc.collect(), 0)
187 for obj in gc.garbage:
188 if id(obj) == id_a:
189 del obj.a
190 break
191 else:
192 self.fail("didn't find obj in garbage (finalizer)")
193 gc.garbage.remove(obj)
Tim Petersead8b7a2004-10-30 23:09:22 +0000194
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200195 @cpython_only
Antoine Pitrou796564c2013-07-30 19:59:21 +0200196 def test_legacy_finalizer_newclass(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000197 # A() is uncollectable if it is part of a cycle, make sure it shows up
198 # in gc.garbage.
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200199 @with_tp_del
Guido van Rossumd8faa362007-04-27 19:54:29 +0000200 class A(object):
Antoine Pitrou796564c2013-07-30 19:59:21 +0200201 def __tp_del__(self): pass
Guido van Rossumd8faa362007-04-27 19:54:29 +0000202 class B(object):
203 pass
204 a = A()
205 a.a = a
206 id_a = id(a)
207 b = B()
208 b.b = b
209 gc.collect()
210 del a
211 del b
212 self.assertNotEqual(gc.collect(), 0)
213 for obj in gc.garbage:
214 if id(obj) == id_a:
215 del obj.a
216 break
217 else:
218 self.fail("didn't find obj in garbage (finalizer)")
219 gc.garbage.remove(obj)
Tim Petersead8b7a2004-10-30 23:09:22 +0000220
Guido van Rossumd8faa362007-04-27 19:54:29 +0000221 def test_function(self):
222 # Tricky: f -> d -> f, code should call d.clear() after the exec to
223 # break the cycle.
224 d = {}
225 exec("def f(): pass\n", d)
226 gc.collect()
227 del d
228 self.assertEqual(gc.collect(), 2)
Tim Petersead8b7a2004-10-30 23:09:22 +0000229
Brett Cannon7a540732011-02-22 03:04:06 +0000230 @refcount_test
Guido van Rossumd8faa362007-04-27 19:54:29 +0000231 def test_frame(self):
232 def f():
233 frame = sys._getframe()
234 gc.collect()
235 f()
236 self.assertEqual(gc.collect(), 1)
Tim Petersead8b7a2004-10-30 23:09:22 +0000237
Guido van Rossumd8faa362007-04-27 19:54:29 +0000238 def test_saveall(self):
239 # Verify that cyclic garbage like lists show up in gc.garbage if the
240 # SAVEALL option is enabled.
Tim Petersead8b7a2004-10-30 23:09:22 +0000241
Guido van Rossumd8faa362007-04-27 19:54:29 +0000242 # First make sure we don't save away other stuff that just happens to
243 # be waiting for collection.
244 gc.collect()
245 # if this fails, someone else created immortal trash
246 self.assertEqual(gc.garbage, [])
247
248 L = []
249 L.append(L)
250 id_L = id(L)
251
252 debug = gc.get_debug()
253 gc.set_debug(debug | gc.DEBUG_SAVEALL)
254 del L
255 gc.collect()
256 gc.set_debug(debug)
257
258 self.assertEqual(len(gc.garbage), 1)
259 obj = gc.garbage.pop()
260 self.assertEqual(id(obj), id_L)
261
262 def test_del(self):
263 # __del__ methods can trigger collection, make this to happen
264 thresholds = gc.get_threshold()
265 gc.enable()
266 gc.set_threshold(1)
267
268 class A:
269 def __del__(self):
270 dir(self)
271 a = A()
272 del a
273
274 gc.disable()
275 gc.set_threshold(*thresholds)
276
277 def test_del_newclass(self):
278 # __del__ methods can trigger collection, make this to happen
279 thresholds = gc.get_threshold()
280 gc.enable()
281 gc.set_threshold(1)
282
283 class A(object):
284 def __del__(self):
285 dir(self)
286 a = A()
287 del a
288
289 gc.disable()
290 gc.set_threshold(*thresholds)
291
Christian Heimesa156e092008-02-16 07:38:31 +0000292 # The following two tests are fragile:
293 # They precisely count the number of allocations,
294 # which is highly implementation-dependent.
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200295 # For example, disposed tuples are not freed, but reused.
296 # To minimize variations, though, we first store the get_count() results
297 # and check them at the end.
Brett Cannon7a540732011-02-22 03:04:06 +0000298 @refcount_test
Guido van Rossumd8faa362007-04-27 19:54:29 +0000299 def test_get_count(self):
300 gc.collect()
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200301 a, b, c = gc.get_count()
302 x = []
303 d, e, f = gc.get_count()
304 self.assertEqual((b, c), (0, 0))
305 self.assertEqual((e, f), (0, 0))
306 # This is less fragile than asserting that a equals 0.
307 self.assertLess(a, 5)
308 # Between the two calls to get_count(), at least one object was
309 # created (the list).
310 self.assertGreater(d, a)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000311
Brett Cannon7a540732011-02-22 03:04:06 +0000312 @refcount_test
Guido van Rossumd8faa362007-04-27 19:54:29 +0000313 def test_collect_generations(self):
314 gc.collect()
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200315 # This object will "trickle" into generation N + 1 after
316 # each call to collect(N)
317 x = []
Guido van Rossumd8faa362007-04-27 19:54:29 +0000318 gc.collect(0)
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200319 # x is now in gen 1
320 a, b, c = gc.get_count()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000321 gc.collect(1)
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200322 # x is now in gen 2
323 d, e, f = gc.get_count()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000324 gc.collect(2)
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200325 # x is now in gen 3
326 g, h, i = gc.get_count()
327 # We don't check a, d, g since their exact values depends on
328 # internal implementation details of the interpreter.
329 self.assertEqual((b, c), (1, 0))
330 self.assertEqual((e, f), (0, 1))
331 self.assertEqual((h, i), (0, 0))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000332
333 def test_trashcan(self):
334 class Ouch:
335 n = 0
336 def __del__(self):
337 Ouch.n = Ouch.n + 1
338 if Ouch.n % 17 == 0:
339 gc.collect()
340
341 # "trashcan" is a hack to prevent stack overflow when deallocating
342 # very deeply nested tuples etc. It works in part by abusing the
343 # type pointer and refcount fields, and that can yield horrible
344 # problems when gc tries to traverse the structures.
345 # If this test fails (as it does in 2.0, 2.1 and 2.2), it will
346 # most likely die via segfault.
347
348 # Note: In 2.3 the possibility for compiling without cyclic gc was
349 # removed, and that in turn allows the trashcan mechanism to work
350 # via much simpler means (e.g., it never abuses the type pointer or
351 # refcount fields anymore). Since it's much less likely to cause a
352 # problem now, the various constants in this expensive (we force a lot
353 # of full collections) test are cut back from the 2.2 version.
354 gc.enable()
355 N = 150
356 for count in range(2):
357 t = []
358 for i in range(N):
359 t = [t, Ouch()]
360 u = []
361 for i in range(N):
362 u = [u, Ouch()]
363 v = {}
364 for i in range(N):
365 v = {1: v, 2: Ouch()}
366 gc.disable()
367
Antoine Pitrou2b0218a2012-09-06 00:59:49 +0200368 def test_trashcan_threads(self):
369 # Issue #13992: trashcan mechanism should be thread-safe
370 NESTING = 60
371 N_THREADS = 2
372
373 def sleeper_gen():
374 """A generator that releases the GIL when closed or dealloc'ed."""
375 try:
376 yield
377 finally:
378 time.sleep(0.000001)
379
380 class C(list):
381 # Appending to a list is atomic, which avoids the use of a lock.
382 inits = []
383 dels = []
384 def __init__(self, alist):
385 self[:] = alist
386 C.inits.append(None)
387 def __del__(self):
388 # This __del__ is called by subtype_dealloc().
389 C.dels.append(None)
390 # `g` will release the GIL when garbage-collected. This
391 # helps assert subtype_dealloc's behaviour when threads
392 # switch in the middle of it.
393 g = sleeper_gen()
394 next(g)
395 # Now that __del__ is finished, subtype_dealloc will proceed
396 # to call list_dealloc, which also uses the trashcan mechanism.
397
398 def make_nested():
399 """Create a sufficiently nested container object so that the
400 trashcan mechanism is invoked when deallocating it."""
401 x = C([])
402 for i in range(NESTING):
403 x = [C([x])]
404 del x
405
406 def run_thread():
407 """Exercise make_nested() in a loop."""
408 while not exit:
409 make_nested()
410
411 old_switchinterval = sys.getswitchinterval()
412 sys.setswitchinterval(1e-5)
413 try:
Serhiy Storchaka263dcd22015-04-01 13:01:14 +0300414 exit = []
Antoine Pitrou2b0218a2012-09-06 00:59:49 +0200415 threads = []
416 for i in range(N_THREADS):
417 t = threading.Thread(target=run_thread)
418 threads.append(t)
Serhiy Storchaka263dcd22015-04-01 13:01:14 +0300419 with start_threads(threads, lambda: exit.append(1)):
Serhiy Storchaka9db55002015-03-28 20:38:37 +0200420 time.sleep(1.0)
Antoine Pitrou2b0218a2012-09-06 00:59:49 +0200421 finally:
422 sys.setswitchinterval(old_switchinterval)
423 gc.collect()
424 self.assertEqual(len(C.inits), len(C.dels))
425
Guido van Rossumd8faa362007-04-27 19:54:29 +0000426 def test_boom(self):
427 class Boom:
428 def __getattr__(self, someattribute):
429 del self.attr
430 raise AttributeError
431
432 a = Boom()
433 b = Boom()
434 a.attr = b
435 b.attr = a
436
437 gc.collect()
438 garbagelen = len(gc.garbage)
439 del a, b
440 # a<->b are in a trash cycle now. Collection will invoke
441 # Boom.__getattr__ (to see whether a and b have __del__ methods), and
442 # __getattr__ deletes the internal "attr" attributes as a side effect.
443 # That causes the trash cycle to get reclaimed via refcounts falling to
444 # 0, thus mutating the trash graph as a side effect of merely asking
445 # whether __del__ exists. This used to (before 2.3b1) crash Python.
446 # Now __getattr__ isn't called.
447 self.assertEqual(gc.collect(), 4)
448 self.assertEqual(len(gc.garbage), garbagelen)
449
450 def test_boom2(self):
451 class Boom2:
452 def __init__(self):
453 self.x = 0
454
455 def __getattr__(self, someattribute):
456 self.x += 1
457 if self.x > 1:
458 del self.attr
459 raise AttributeError
460
461 a = Boom2()
462 b = Boom2()
463 a.attr = b
464 b.attr = a
465
466 gc.collect()
467 garbagelen = len(gc.garbage)
468 del a, b
469 # Much like test_boom(), except that __getattr__ doesn't break the
470 # cycle until the second time gc checks for __del__. As of 2.3b1,
471 # there isn't a second time, so this simply cleans up the trash cycle.
472 # We expect a, b, a.__dict__ and b.__dict__ (4 objects) to get
473 # reclaimed this way.
474 self.assertEqual(gc.collect(), 4)
475 self.assertEqual(len(gc.garbage), garbagelen)
476
477 def test_boom_new(self):
478 # boom__new and boom2_new are exactly like boom and boom2, except use
479 # new-style classes.
480
481 class Boom_New(object):
482 def __getattr__(self, someattribute):
483 del self.attr
484 raise AttributeError
485
486 a = Boom_New()
487 b = Boom_New()
488 a.attr = b
489 b.attr = a
490
491 gc.collect()
492 garbagelen = len(gc.garbage)
493 del a, b
494 self.assertEqual(gc.collect(), 4)
495 self.assertEqual(len(gc.garbage), garbagelen)
496
497 def test_boom2_new(self):
498 class Boom2_New(object):
499 def __init__(self):
500 self.x = 0
501
502 def __getattr__(self, someattribute):
503 self.x += 1
504 if self.x > 1:
505 del self.attr
506 raise AttributeError
507
508 a = Boom2_New()
509 b = Boom2_New()
510 a.attr = b
511 b.attr = a
512
513 gc.collect()
514 garbagelen = len(gc.garbage)
515 del a, b
516 self.assertEqual(gc.collect(), 4)
517 self.assertEqual(len(gc.garbage), garbagelen)
518
519 def test_get_referents(self):
520 alist = [1, 3, 5]
521 got = gc.get_referents(alist)
522 got.sort()
523 self.assertEqual(got, alist)
524
525 atuple = tuple(alist)
526 got = gc.get_referents(atuple)
527 got.sort()
528 self.assertEqual(got, alist)
529
530 adict = {1: 3, 5: 7}
531 expected = [1, 3, 5, 7]
532 got = gc.get_referents(adict)
533 got.sort()
534 self.assertEqual(got, expected)
535
536 got = gc.get_referents([1, 2], {3: 4}, (0, 0, 0))
537 got.sort()
Guido van Rossum805365e2007-05-07 22:24:25 +0000538 self.assertEqual(got, [0, 0] + list(range(5)))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000539
540 self.assertEqual(gc.get_referents(1, 'a', 4j), [])
541
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000542 def test_is_tracked(self):
543 # Atomic built-in types are not tracked, user-defined objects and
544 # mutable containers are.
545 # NOTE: types with special optimizations (e.g. tuple) have tests
546 # in their own test files instead.
547 self.assertFalse(gc.is_tracked(None))
548 self.assertFalse(gc.is_tracked(1))
549 self.assertFalse(gc.is_tracked(1.0))
550 self.assertFalse(gc.is_tracked(1.0 + 5.0j))
551 self.assertFalse(gc.is_tracked(True))
552 self.assertFalse(gc.is_tracked(False))
553 self.assertFalse(gc.is_tracked(b"a"))
554 self.assertFalse(gc.is_tracked("a"))
555 self.assertFalse(gc.is_tracked(bytearray(b"a")))
556 self.assertFalse(gc.is_tracked(type))
557 self.assertFalse(gc.is_tracked(int))
558 self.assertFalse(gc.is_tracked(object))
559 self.assertFalse(gc.is_tracked(object()))
560
561 class UserClass:
562 pass
Antoine Pitroua63cc212015-04-13 20:10:06 +0200563
564 class UserInt(int):
565 pass
566
567 # Base class is object; no extra fields.
568 class UserClassSlots:
569 __slots__ = ()
570
571 # Base class is fixed size larger than object; no extra fields.
572 class UserFloatSlots(float):
573 __slots__ = ()
574
575 # Base class is variable size; no extra fields.
576 class UserIntSlots(int):
577 __slots__ = ()
578
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000579 self.assertTrue(gc.is_tracked(gc))
580 self.assertTrue(gc.is_tracked(UserClass))
581 self.assertTrue(gc.is_tracked(UserClass()))
Antoine Pitroua63cc212015-04-13 20:10:06 +0200582 self.assertTrue(gc.is_tracked(UserInt()))
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000583 self.assertTrue(gc.is_tracked([]))
584 self.assertTrue(gc.is_tracked(set()))
Antoine Pitroua63cc212015-04-13 20:10:06 +0200585 self.assertFalse(gc.is_tracked(UserClassSlots()))
586 self.assertFalse(gc.is_tracked(UserFloatSlots()))
587 self.assertFalse(gc.is_tracked(UserIntSlots()))
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000588
Guido van Rossumd8faa362007-04-27 19:54:29 +0000589 def test_bug1055820b(self):
590 # Corresponds to temp2b.py in the bug report.
591
592 ouch = []
593 def callback(ignored):
594 ouch[:] = [wr() for wr in WRs]
595
596 Cs = [C1055820(i) for i in range(2)]
597 WRs = [weakref.ref(c, callback) for c in Cs]
598 c = None
599
600 gc.collect()
601 self.assertEqual(len(ouch), 0)
602 # Make the two instances trash, and collect again. The bug was that
603 # the callback materialized a strong reference to an instance, but gc
604 # cleared the instance's dict anyway.
605 Cs = None
606 gc.collect()
607 self.assertEqual(len(ouch), 2) # else the callbacks didn't run
608 for x in ouch:
609 # If the callback resurrected one of these guys, the instance
610 # would be damaged, with an empty __dict__.
611 self.assertEqual(x, None)
612
Tim Peters5fbc7b12014-05-08 17:42:19 -0500613 def test_bug21435(self):
614 # This is a poor test - its only virtue is that it happened to
615 # segfault on Tim's Windows box before the patch for 21435 was
616 # applied. That's a nasty bug relying on specific pieces of cyclic
617 # trash appearing in exactly the right order in finalize_garbage()'s
618 # input list.
619 # But there's no reliable way to force that order from Python code,
620 # so over time chances are good this test won't really be testing much
621 # of anything anymore. Still, if it blows up, there's _some_
622 # problem ;-)
623 gc.collect()
624
625 class A:
626 pass
627
628 class B:
629 def __init__(self, x):
630 self.x = x
631
632 def __del__(self):
633 self.attr = None
634
635 def do_work():
636 a = A()
637 b = B(A())
638
639 a.attr = b
640 b.attr = a
641
642 do_work()
643 gc.collect() # this blows up (bad C pointer) when it fails
644
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200645 @cpython_only
Antoine Pitrou696e0352010-08-08 22:18:46 +0000646 def test_garbage_at_shutdown(self):
647 import subprocess
648 code = """if 1:
649 import gc
Antoine Pitrou796564c2013-07-30 19:59:21 +0200650 import _testcapi
651 @_testcapi.with_tp_del
Antoine Pitrou696e0352010-08-08 22:18:46 +0000652 class X:
653 def __init__(self, name):
654 self.name = name
655 def __repr__(self):
656 return "<X %%r>" %% self.name
Antoine Pitrou796564c2013-07-30 19:59:21 +0200657 def __tp_del__(self):
Antoine Pitrou696e0352010-08-08 22:18:46 +0000658 pass
659
660 x = X('first')
661 x.x = x
662 x.y = X('second')
663 del x
Antoine Pitrou2ed94eb2010-09-14 09:48:39 +0000664 gc.set_debug(%s)
Antoine Pitrou696e0352010-08-08 22:18:46 +0000665 """
666 def run_command(code):
Georg Brandl08be72d2010-10-24 15:11:22 +0000667 p = subprocess.Popen([sys.executable, "-Wd", "-c", code],
Antoine Pitrou696e0352010-08-08 22:18:46 +0000668 stdout=subprocess.PIPE,
669 stderr=subprocess.PIPE)
670 stdout, stderr = p.communicate()
Brian Curtin8291af22010-11-01 16:40:17 +0000671 p.stdout.close()
672 p.stderr.close()
Antoine Pitrou696e0352010-08-08 22:18:46 +0000673 self.assertEqual(p.returncode, 0)
Victor Stinner6cac1132019-12-08 08:38:16 +0100674 self.assertEqual(stdout, b"")
675 return stderr
Antoine Pitrou696e0352010-08-08 22:18:46 +0000676
Antoine Pitrou2ed94eb2010-09-14 09:48:39 +0000677 stderr = run_command(code % "0")
Georg Brandl08be72d2010-10-24 15:11:22 +0000678 self.assertIn(b"ResourceWarning: gc: 2 uncollectable objects at "
679 b"shutdown; use", stderr)
Antoine Pitrouaee47562010-09-16 15:04:49 +0000680 self.assertNotIn(b"<X 'first'>", stderr)
Antoine Pitrou696e0352010-08-08 22:18:46 +0000681 # With DEBUG_UNCOLLECTABLE, the garbage list gets printed
Antoine Pitrou2ed94eb2010-09-14 09:48:39 +0000682 stderr = run_command(code % "gc.DEBUG_UNCOLLECTABLE")
Georg Brandl08be72d2010-10-24 15:11:22 +0000683 self.assertIn(b"ResourceWarning: gc: 2 uncollectable objects at "
684 b"shutdown", stderr)
Antoine Pitrouaee47562010-09-16 15:04:49 +0000685 self.assertTrue(
686 (b"[<X 'first'>, <X 'second'>]" in stderr) or
687 (b"[<X 'second'>, <X 'first'>]" in stderr), stderr)
Antoine Pitrou2ed94eb2010-09-14 09:48:39 +0000688 # With DEBUG_SAVEALL, no additional message should get printed
689 # (because gc.garbage also contains normally reclaimable cyclic
690 # references, and its elements get printed at runtime anyway).
691 stderr = run_command(code % "gc.DEBUG_SAVEALL")
692 self.assertNotIn(b"uncollectable objects at shutdown", stderr)
693
Serhiy Storchakaa7930372016-07-03 22:27:26 +0300694 @requires_type_collecting
Antoine Pitrou5f454a02013-05-06 21:15:57 +0200695 def test_gc_main_module_at_shutdown(self):
696 # Create a reference cycle through the __main__ module and check
697 # it gets collected at interpreter shutdown.
698 code = """if 1:
Antoine Pitrou5f454a02013-05-06 21:15:57 +0200699 class C:
700 def __del__(self):
701 print('__del__ called')
702 l = [C()]
703 l.append(l)
704 """
705 rc, out, err = assert_python_ok('-c', code)
706 self.assertEqual(out.strip(), b'__del__ called')
707
Serhiy Storchakaa7930372016-07-03 22:27:26 +0300708 @requires_type_collecting
Antoine Pitrou5f454a02013-05-06 21:15:57 +0200709 def test_gc_ordinary_module_at_shutdown(self):
710 # Same as above, but with a non-__main__ module.
711 with temp_dir() as script_dir:
712 module = """if 1:
Antoine Pitrou5f454a02013-05-06 21:15:57 +0200713 class C:
714 def __del__(self):
715 print('__del__ called')
716 l = [C()]
717 l.append(l)
718 """
719 code = """if 1:
720 import sys
721 sys.path.insert(0, %r)
722 import gctest
723 """ % (script_dir,)
724 make_script(script_dir, 'gctest', module)
725 rc, out, err = assert_python_ok('-c', code)
726 self.assertEqual(out.strip(), b'__del__ called')
727
Zackery Spytzd8cba5d2018-07-03 13:47:22 -0600728 @requires_type_collecting
729 def test_global_del_SystemExit(self):
730 code = """if 1:
731 class ClassWithDel:
732 def __del__(self):
733 print('__del__ called')
734 a = ClassWithDel()
735 a.link = a
736 raise SystemExit(0)"""
737 self.addCleanup(unlink, TESTFN)
738 with open(TESTFN, 'w') as script:
739 script.write(code)
740 rc, out, err = assert_python_ok(TESTFN)
741 self.assertEqual(out.strip(), b'__del__ called')
742
Antoine Pitroud4156c12012-10-30 22:43:19 +0100743 def test_get_stats(self):
744 stats = gc.get_stats()
745 self.assertEqual(len(stats), 3)
746 for st in stats:
747 self.assertIsInstance(st, dict)
748 self.assertEqual(set(st),
749 {"collected", "collections", "uncollectable"})
750 self.assertGreaterEqual(st["collected"], 0)
751 self.assertGreaterEqual(st["collections"], 0)
752 self.assertGreaterEqual(st["uncollectable"], 0)
753 # Check that collection counts are incremented correctly
754 if gc.isenabled():
755 self.addCleanup(gc.enable)
756 gc.disable()
757 old = gc.get_stats()
758 gc.collect(0)
759 new = gc.get_stats()
760 self.assertEqual(new[0]["collections"], old[0]["collections"] + 1)
761 self.assertEqual(new[1]["collections"], old[1]["collections"])
762 self.assertEqual(new[2]["collections"], old[2]["collections"])
763 gc.collect(2)
764 new = gc.get_stats()
765 self.assertEqual(new[0]["collections"], old[0]["collections"] + 1)
766 self.assertEqual(new[1]["collections"], old[1]["collections"])
767 self.assertEqual(new[2]["collections"], old[2]["collections"] + 1)
768
brainfvckc75edab2017-10-16 12:49:41 -0700769 def test_freeze(self):
770 gc.freeze()
771 self.assertGreater(gc.get_freeze_count(), 0)
772 gc.unfreeze()
773 self.assertEqual(gc.get_freeze_count(), 0)
774
Pablo Galindo175421b2019-02-23 03:02:06 +0000775 def test_get_objects(self):
776 gc.collect()
777 l = []
778 l.append(l)
Pablo Galindod60a79a2019-03-01 01:12:27 -0800779 self.assertTrue(
780 any(l is element for element in gc.get_objects(generation=0))
781 )
782 self.assertFalse(
783 any(l is element for element in gc.get_objects(generation=1))
784 )
785 self.assertFalse(
786 any(l is element for element in gc.get_objects(generation=2))
787 )
Pablo Galindo175421b2019-02-23 03:02:06 +0000788 gc.collect(generation=0)
Pablo Galindod60a79a2019-03-01 01:12:27 -0800789 self.assertFalse(
790 any(l is element for element in gc.get_objects(generation=0))
791 )
792 self.assertTrue(
793 any(l is element for element in gc.get_objects(generation=1))
794 )
795 self.assertFalse(
796 any(l is element for element in gc.get_objects(generation=2))
797 )
Pablo Galindo175421b2019-02-23 03:02:06 +0000798 gc.collect(generation=1)
Pablo Galindod60a79a2019-03-01 01:12:27 -0800799 self.assertFalse(
800 any(l is element for element in gc.get_objects(generation=0))
801 )
802 self.assertFalse(
803 any(l is element for element in gc.get_objects(generation=1))
804 )
805 self.assertTrue(
806 any(l is element for element in gc.get_objects(generation=2))
807 )
Pablo Galindo175421b2019-02-23 03:02:06 +0000808 gc.collect(generation=2)
Pablo Galindod60a79a2019-03-01 01:12:27 -0800809 self.assertFalse(
810 any(l is element for element in gc.get_objects(generation=0))
811 )
812 self.assertFalse(
813 any(l is element for element in gc.get_objects(generation=1))
814 )
815 self.assertTrue(
816 any(l is element for element in gc.get_objects(generation=2))
817 )
Pablo Galindo175421b2019-02-23 03:02:06 +0000818 del l
819 gc.collect()
820
821 def test_get_objects_arguments(self):
822 gc.collect()
823 self.assertEqual(len(gc.get_objects()),
824 len(gc.get_objects(generation=None)))
825
826 self.assertRaises(ValueError, gc.get_objects, 1000)
827 self.assertRaises(ValueError, gc.get_objects, -1000)
828 self.assertRaises(TypeError, gc.get_objects, "1")
829 self.assertRaises(TypeError, gc.get_objects, 1.234)
830
Pablo Galindo466326d2019-10-13 16:48:59 +0100831 def test_resurrection_only_happens_once_per_object(self):
832 class A: # simple self-loop
833 def __init__(self):
834 self.me = self
835
836 class Lazarus(A):
837 resurrected = 0
838 resurrected_instances = []
839
840 def __del__(self):
841 Lazarus.resurrected += 1
842 Lazarus.resurrected_instances.append(self)
843
844 gc.collect()
845 gc.disable()
846
847 # We start with 0 resurrections
848 laz = Lazarus()
849 self.assertEqual(Lazarus.resurrected, 0)
850
851 # Deleting the instance and triggering a collection
852 # resurrects the object
853 del laz
854 gc.collect()
855 self.assertEqual(Lazarus.resurrected, 1)
856 self.assertEqual(len(Lazarus.resurrected_instances), 1)
857
858 # Clearing the references and forcing a collection
859 # should not resurrect the object again.
860 Lazarus.resurrected_instances.clear()
861 self.assertEqual(Lazarus.resurrected, 1)
862 gc.collect()
863 self.assertEqual(Lazarus.resurrected, 1)
864
865 gc.enable()
866
867 def test_resurrection_is_transitive(self):
868 class Cargo:
869 def __init__(self):
870 self.me = self
871
872 class Lazarus:
873 resurrected_instances = []
874
875 def __del__(self):
876 Lazarus.resurrected_instances.append(self)
877
878 gc.collect()
879 gc.disable()
880
881 laz = Lazarus()
882 cargo = Cargo()
883 cargo_id = id(cargo)
884
885 # Create a cycle between cargo and laz
886 laz.cargo = cargo
887 cargo.laz = laz
888
889 # Drop the references, force a collection and check that
890 # everything was resurrected.
891 del laz, cargo
892 gc.collect()
893 self.assertEqual(len(Lazarus.resurrected_instances), 1)
894 instance = Lazarus.resurrected_instances.pop()
895 self.assertTrue(hasattr(instance, "cargo"))
896 self.assertEqual(id(instance.cargo), cargo_id)
897
898 gc.collect()
899 gc.enable()
900
901 def test_resurrection_does_not_block_cleanup_of_other_objects(self):
902
Tim Petersecbf35f2019-10-09 12:37:30 -0500903 # When a finalizer resurrects objects, stats were reporting them as
904 # having been collected. This affected both collect()'s return
905 # value and the dicts returned by get_stats().
906 N = 100
907
908 class A: # simple self-loop
909 def __init__(self):
910 self.me = self
911
912 class Z(A): # resurrecting __del__
913 def __del__(self):
914 zs.append(self)
915
916 zs = []
917
918 def getstats():
919 d = gc.get_stats()[-1]
920 return d['collected'], d['uncollectable']
921
922 gc.collect()
923 gc.disable()
924
925 # No problems if just collecting A() instances.
926 oldc, oldnc = getstats()
927 for i in range(N):
928 A()
929 t = gc.collect()
930 c, nc = getstats()
931 self.assertEqual(t, 2*N) # instance object & its dict
932 self.assertEqual(c - oldc, 2*N)
933 self.assertEqual(nc - oldnc, 0)
934
935 # But Z() is not actually collected.
936 oldc, oldnc = c, nc
937 Z()
938 # Nothing is collected - Z() is merely resurrected.
939 t = gc.collect()
940 c, nc = getstats()
Pablo Galindo466326d2019-10-13 16:48:59 +0100941 self.assertEqual(t, 0)
942 self.assertEqual(c - oldc, 0)
Tim Petersecbf35f2019-10-09 12:37:30 -0500943 self.assertEqual(nc - oldnc, 0)
944
Pablo Galindo466326d2019-10-13 16:48:59 +0100945 # Z() should not prevent anything else from being collected.
Tim Petersecbf35f2019-10-09 12:37:30 -0500946 oldc, oldnc = c, nc
947 for i in range(N):
948 A()
949 Z()
Tim Petersecbf35f2019-10-09 12:37:30 -0500950 t = gc.collect()
951 c, nc = getstats()
952 self.assertEqual(t, 2*N)
953 self.assertEqual(c - oldc, 2*N)
954 self.assertEqual(nc - oldnc, 0)
955
Pablo Galindo466326d2019-10-13 16:48:59 +0100956 # The A() trash should have been reclaimed already but the
957 # 2 copies of Z are still in zs (and the associated dicts).
958 oldc, oldnc = c, nc
959 zs.clear()
960 t = gc.collect()
961 c, nc = getstats()
962 self.assertEqual(t, 4)
963 self.assertEqual(c - oldc, 4)
964 self.assertEqual(nc - oldnc, 0)
965
Tim Petersecbf35f2019-10-09 12:37:30 -0500966 gc.enable()
Antoine Pitrou696e0352010-08-08 22:18:46 +0000967
Neil Schemenauer392a13b2019-10-15 20:56:48 -0700968 @unittest.skipIf(ContainerNoGC is None,
969 'requires ContainerNoGC extension type')
970 def test_trash_weakref_clear(self):
971 # Test that trash weakrefs are properly cleared (bpo-38006).
972 #
973 # Structure we are creating:
974 #
975 # Z <- Y <- A--+--> WZ -> C
976 # ^ |
977 # +--+
978 # where:
979 # WZ is a weakref to Z with callback C
980 # Y doesn't implement tp_traverse
981 # A contains a reference to itself, Y and WZ
982 #
983 # A, Y, Z, WZ are all trash. The GC doesn't know that Z is trash
984 # because Y does not implement tp_traverse. To show the bug, WZ needs
985 # to live long enough so that Z is deallocated before it. Then, if
986 # gcmodule is buggy, when Z is being deallocated, C will run.
987 #
988 # To ensure WZ lives long enough, we put it in a second reference
989 # cycle. That trick only works due to the ordering of the GC prev/next
990 # linked lists. So, this test is a bit fragile.
991 #
992 # The bug reported in bpo-38006 is caused because the GC did not
993 # clear WZ before starting the process of calling tp_clear on the
994 # trash. Normally, handle_weakrefs() would find the weakref via Z and
995 # clear it. However, since the GC cannot find Z, WR is not cleared and
996 # it can execute during delete_garbage(). That can lead to disaster
997 # since the callback might tinker with objects that have already had
998 # tp_clear called on them (leaving them in possibly invalid states).
999
1000 callback = unittest.mock.Mock()
1001
1002 class A:
1003 __slots__ = ['a', 'y', 'wz']
1004
1005 class Z:
1006 pass
1007
1008 # setup required object graph, as described above
1009 a = A()
1010 a.a = a
1011 a.y = ContainerNoGC(Z())
1012 a.wz = weakref.ref(a.y.value, callback)
1013 # create second cycle to keep WZ alive longer
1014 wr_cycle = [a.wz]
1015 wr_cycle.append(wr_cycle)
1016 # ensure trash unrelated to this test is gone
1017 gc.collect()
1018 gc.disable()
1019 # release references and create trash
1020 del a, wr_cycle
1021 gc.collect()
1022 # if called, it means there is a bug in the GC. The weakref should be
1023 # cleared before Z dies.
1024 callback.assert_not_called()
1025 gc.enable()
1026
1027
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +00001028class GCCallbackTests(unittest.TestCase):
1029 def setUp(self):
1030 # Save gc state and disable it.
1031 self.enabled = gc.isenabled()
1032 gc.disable()
1033 self.debug = gc.get_debug()
1034 gc.set_debug(0)
1035 gc.callbacks.append(self.cb1)
1036 gc.callbacks.append(self.cb2)
Antoine Pitrou6b64fc62012-04-16 21:29:02 +02001037 self.othergarbage = []
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +00001038
1039 def tearDown(self):
1040 # Restore gc state
1041 del self.visit
1042 gc.callbacks.remove(self.cb1)
1043 gc.callbacks.remove(self.cb2)
1044 gc.set_debug(self.debug)
1045 if self.enabled:
1046 gc.enable()
1047 # destroy any uncollectables
1048 gc.collect()
1049 for obj in gc.garbage:
1050 if isinstance(obj, Uncollectable):
1051 obj.partner = None
1052 del gc.garbage[:]
Antoine Pitrou6b64fc62012-04-16 21:29:02 +02001053 del self.othergarbage
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +00001054 gc.collect()
1055
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +00001056 def preclean(self):
1057 # Remove all fluff from the system. Invoke this function
1058 # manually rather than through self.setUp() for maximum
1059 # safety.
1060 self.visit = []
1061 gc.collect()
1062 garbage, gc.garbage[:] = gc.garbage[:], []
1063 self.othergarbage.append(garbage)
1064 self.visit = []
1065
1066 def cb1(self, phase, info):
1067 self.visit.append((1, phase, dict(info)))
1068
1069 def cb2(self, phase, info):
1070 self.visit.append((2, phase, dict(info)))
1071 if phase == "stop" and hasattr(self, "cleanup"):
1072 # Clean Uncollectable from garbage
1073 uc = [e for e in gc.garbage if isinstance(e, Uncollectable)]
1074 gc.garbage[:] = [e for e in gc.garbage
1075 if not isinstance(e, Uncollectable)]
1076 for e in uc:
1077 e.partner = None
1078
Antoine Pitroude3c73b2012-04-16 21:29:58 +02001079 def test_collect(self):
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +00001080 self.preclean()
1081 gc.collect()
1082 # Algorithmically verify the contents of self.visit
1083 # because it is long and tortuous.
1084
1085 # Count the number of visits to each callback
1086 n = [v[0] for v in self.visit]
1087 n1 = [i for i in n if i == 1]
1088 n2 = [i for i in n if i == 2]
1089 self.assertEqual(n1, [1]*2)
1090 self.assertEqual(n2, [2]*2)
1091
1092 # Count that we got the right number of start and stop callbacks.
1093 n = [v[1] for v in self.visit]
1094 n1 = [i for i in n if i == "start"]
1095 n2 = [i for i in n if i == "stop"]
1096 self.assertEqual(n1, ["start"]*2)
1097 self.assertEqual(n2, ["stop"]*2)
1098
1099 # Check that we got the right info dict for all callbacks
1100 for v in self.visit:
1101 info = v[2]
1102 self.assertTrue("generation" in info)
1103 self.assertTrue("collected" in info)
1104 self.assertTrue("uncollectable" in info)
1105
Antoine Pitroude3c73b2012-04-16 21:29:58 +02001106 def test_collect_generation(self):
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +00001107 self.preclean()
1108 gc.collect(2)
1109 for v in self.visit:
1110 info = v[2]
1111 self.assertEqual(info["generation"], 2)
1112
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001113 @cpython_only
Antoine Pitroude3c73b2012-04-16 21:29:58 +02001114 def test_collect_garbage(self):
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +00001115 self.preclean()
1116 # Each of these cause four objects to be garbage: Two
Min ho Kim39d87b52019-08-31 06:21:19 +10001117 # Uncollectables and their instance dicts.
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +00001118 Uncollectable()
1119 Uncollectable()
1120 C1055820(666)
1121 gc.collect()
1122 for v in self.visit:
1123 if v[1] != "stop":
1124 continue
1125 info = v[2]
1126 self.assertEqual(info["collected"], 2)
1127 self.assertEqual(info["uncollectable"], 8)
1128
1129 # We should now have the Uncollectables in gc.garbage
1130 self.assertEqual(len(gc.garbage), 4)
1131 for e in gc.garbage:
1132 self.assertIsInstance(e, Uncollectable)
1133
1134 # Now, let our callback handle the Uncollectable instances
1135 self.cleanup=True
1136 self.visit = []
1137 gc.garbage[:] = []
1138 gc.collect()
1139 for v in self.visit:
1140 if v[1] != "stop":
1141 continue
1142 info = v[2]
1143 self.assertEqual(info["collected"], 0)
1144 self.assertEqual(info["uncollectable"], 4)
1145
1146 # Uncollectables should be gone
1147 self.assertEqual(len(gc.garbage), 0)
1148
1149
Victor Stinner626bff82018-10-25 17:31:10 +02001150 @unittest.skipIf(BUILD_WITH_NDEBUG,
1151 'built with -NDEBUG')
1152 def test_refcount_errors(self):
1153 self.preclean()
1154 # Verify the "handling" of objects with broken refcounts
1155
1156 # Skip the test if ctypes is not available
1157 import_module("ctypes")
1158
1159 import subprocess
1160 code = textwrap.dedent('''
1161 from test.support import gc_collect, SuppressCrashReport
1162
1163 a = [1, 2, 3]
1164 b = [a]
1165
1166 # Avoid coredump when Py_FatalError() calls abort()
1167 SuppressCrashReport().__enter__()
1168
1169 # Simulate the refcount of "a" being too low (compared to the
1170 # references held on it by live data), but keeping it above zero
1171 # (to avoid deallocating it):
1172 import ctypes
1173 ctypes.pythonapi.Py_DecRef(ctypes.py_object(a))
1174
1175 # The garbage collector should now have a fatal error
1176 # when it reaches the broken object
1177 gc_collect()
1178 ''')
1179 p = subprocess.Popen([sys.executable, "-c", code],
1180 stdout=subprocess.PIPE,
1181 stderr=subprocess.PIPE)
1182 stdout, stderr = p.communicate()
1183 p.stdout.close()
1184 p.stderr.close()
1185 # Verify that stderr has a useful error message:
1186 self.assertRegex(stderr,
1187 br'gcmodule\.c:[0-9]+: gc_decref: Assertion "gc_get_refs\(g\) > 0" failed.')
1188 self.assertRegex(stderr,
1189 br'refcount is too small')
Victor Stinner626bff82018-10-25 17:31:10 +02001190 # "address : 0x7fb5062efc18"
1191 # "address : 7FB5062EFC18"
Victor Stinner68762572019-10-07 18:42:01 +02001192 address_regex = br'[0-9a-fA-Fx]+'
Victor Stinner626bff82018-10-25 17:31:10 +02001193 self.assertRegex(stderr,
Victor Stinner68762572019-10-07 18:42:01 +02001194 br'object address : ' + address_regex)
1195 self.assertRegex(stderr,
1196 br'object refcount : 1')
1197 self.assertRegex(stderr,
1198 br'object type : ' + address_regex)
1199 self.assertRegex(stderr,
1200 br'object type name: list')
1201 self.assertRegex(stderr,
1202 br'object repr : \[1, 2, 3\]')
Victor Stinner626bff82018-10-25 17:31:10 +02001203
1204
Guido van Rossumd8faa362007-04-27 19:54:29 +00001205class GCTogglingTests(unittest.TestCase):
1206 def setUp(self):
1207 gc.enable()
1208
1209 def tearDown(self):
1210 gc.disable()
1211
1212 def test_bug1055820c(self):
1213 # Corresponds to temp2c.py in the bug report. This is pretty
1214 # elaborate.
1215
1216 c0 = C1055820(0)
1217 # Move c0 into generation 2.
1218 gc.collect()
1219
1220 c1 = C1055820(1)
1221 c1.keep_c0_alive = c0
1222 del c0.loop # now only c1 keeps c0 alive
1223
1224 c2 = C1055820(2)
1225 c2wr = weakref.ref(c2) # no callback!
1226
1227 ouch = []
1228 def callback(ignored):
Tim Petersead8b7a2004-10-30 23:09:22 +00001229 ouch[:] = [c2wr()]
1230
Guido van Rossumd8faa362007-04-27 19:54:29 +00001231 # The callback gets associated with a wr on an object in generation 2.
1232 c0wr = weakref.ref(c0, callback)
Tim Petersead8b7a2004-10-30 23:09:22 +00001233
Guido van Rossumd8faa362007-04-27 19:54:29 +00001234 c0 = c1 = c2 = None
Tim Petersead8b7a2004-10-30 23:09:22 +00001235
Guido van Rossumd8faa362007-04-27 19:54:29 +00001236 # What we've set up: c0, c1, and c2 are all trash now. c0 is in
1237 # generation 2. The only thing keeping it alive is that c1 points to
1238 # it. c1 and c2 are in generation 0, and are in self-loops. There's a
1239 # global weakref to c2 (c2wr), but that weakref has no callback.
1240 # There's also a global weakref to c0 (c0wr), and that does have a
1241 # callback, and that callback references c2 via c2wr().
1242 #
1243 # c0 has a wr with callback, which references c2wr
1244 # ^
1245 # |
1246 # | Generation 2 above dots
1247 #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . .
1248 # | Generation 0 below dots
1249 # |
1250 # |
1251 # ^->c1 ^->c2 has a wr but no callback
1252 # | | | |
1253 # <--v <--v
1254 #
1255 # So this is the nightmare: when generation 0 gets collected, we see
1256 # that c2 has a callback-free weakref, and c1 doesn't even have a
1257 # weakref. Collecting generation 0 doesn't see c0 at all, and c0 is
1258 # the only object that has a weakref with a callback. gc clears c1
1259 # and c2. Clearing c1 has the side effect of dropping the refcount on
1260 # c0 to 0, so c0 goes away (despite that it's in an older generation)
1261 # and c0's wr callback triggers. That in turn materializes a reference
1262 # to c2 via c2wr(), but c2 gets cleared anyway by gc.
Tim Petersead8b7a2004-10-30 23:09:22 +00001263
Guido van Rossumd8faa362007-04-27 19:54:29 +00001264 # We want to let gc happen "naturally", to preserve the distinction
1265 # between generations.
1266 junk = []
1267 i = 0
1268 detector = GC_Detector()
1269 while not detector.gc_happened:
1270 i += 1
1271 if i > 10000:
1272 self.fail("gc didn't happen after 10000 iterations")
1273 self.assertEqual(len(ouch), 0)
1274 junk.append([]) # this will eventually trigger gc
Tim Petersead8b7a2004-10-30 23:09:22 +00001275
Guido van Rossumd8faa362007-04-27 19:54:29 +00001276 self.assertEqual(len(ouch), 1) # else the callback wasn't invoked
1277 for x in ouch:
1278 # If the callback resurrected c2, the instance would be damaged,
1279 # with an empty __dict__.
1280 self.assertEqual(x, None)
Tim Petersead8b7a2004-10-30 23:09:22 +00001281
Guido van Rossumd8faa362007-04-27 19:54:29 +00001282 def test_bug1055820d(self):
1283 # Corresponds to temp2d.py in the bug report. This is very much like
1284 # test_bug1055820c, but uses a __del__ method instead of a weakref
1285 # callback to sneak in a resurrection of cyclic trash.
Tim Petersead8b7a2004-10-30 23:09:22 +00001286
Guido van Rossumd8faa362007-04-27 19:54:29 +00001287 ouch = []
1288 class D(C1055820):
1289 def __del__(self):
1290 ouch[:] = [c2wr()]
Tim Petersead8b7a2004-10-30 23:09:22 +00001291
Guido van Rossumd8faa362007-04-27 19:54:29 +00001292 d0 = D(0)
1293 # Move all the above into generation 2.
1294 gc.collect()
Tim Petersead8b7a2004-10-30 23:09:22 +00001295
Guido van Rossumd8faa362007-04-27 19:54:29 +00001296 c1 = C1055820(1)
1297 c1.keep_d0_alive = d0
1298 del d0.loop # now only c1 keeps d0 alive
Tim Petersead8b7a2004-10-30 23:09:22 +00001299
Guido van Rossumd8faa362007-04-27 19:54:29 +00001300 c2 = C1055820(2)
1301 c2wr = weakref.ref(c2) # no callback!
Tim Petersead8b7a2004-10-30 23:09:22 +00001302
Guido van Rossumd8faa362007-04-27 19:54:29 +00001303 d0 = c1 = c2 = None
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +00001304
Guido van Rossumd8faa362007-04-27 19:54:29 +00001305 # What we've set up: d0, c1, and c2 are all trash now. d0 is in
1306 # generation 2. The only thing keeping it alive is that c1 points to
1307 # it. c1 and c2 are in generation 0, and are in self-loops. There's
1308 # a global weakref to c2 (c2wr), but that weakref has no callback.
1309 # There are no other weakrefs.
1310 #
1311 # d0 has a __del__ method that references c2wr
1312 # ^
1313 # |
1314 # | Generation 2 above dots
1315 #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . .
1316 # | Generation 0 below dots
1317 # |
1318 # |
1319 # ^->c1 ^->c2 has a wr but no callback
1320 # | | | |
1321 # <--v <--v
1322 #
1323 # So this is the nightmare: when generation 0 gets collected, we see
1324 # that c2 has a callback-free weakref, and c1 doesn't even have a
1325 # weakref. Collecting generation 0 doesn't see d0 at all. gc clears
1326 # c1 and c2. Clearing c1 has the side effect of dropping the refcount
1327 # on d0 to 0, so d0 goes away (despite that it's in an older
1328 # generation) and d0's __del__ triggers. That in turn materializes
1329 # a reference to c2 via c2wr(), but c2 gets cleared anyway by gc.
1330
1331 # We want to let gc happen "naturally", to preserve the distinction
1332 # between generations.
1333 detector = GC_Detector()
1334 junk = []
1335 i = 0
1336 while not detector.gc_happened:
1337 i += 1
1338 if i > 10000:
1339 self.fail("gc didn't happen after 10000 iterations")
1340 self.assertEqual(len(ouch), 0)
1341 junk.append([]) # this will eventually trigger gc
1342
1343 self.assertEqual(len(ouch), 1) # else __del__ wasn't invoked
1344 for x in ouch:
1345 # If __del__ resurrected c2, the instance would be damaged, with an
1346 # empty __dict__.
1347 self.assertEqual(x, None)
1348
1349def test_main():
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +00001350 enabled = gc.isenabled()
1351 gc.disable()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001352 assert not gc.isenabled()
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001353 debug = gc.get_debug()
1354 gc.set_debug(debug & ~gc.DEBUG_LEAK) # this test is supposed to leak
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +00001355
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001356 try:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001357 gc.collect() # Delete 2nd generation garbage
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +00001358 run_unittest(GCTests, GCTogglingTests, GCCallbackTests)
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001359 finally:
1360 gc.set_debug(debug)
1361 # test gc.enable() even if GC is disabled by default
1362 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001363 print("restoring automatic collection")
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001364 # make sure to always test gc.enable()
1365 gc.enable()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001366 assert gc.isenabled()
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001367 if not enabled:
1368 gc.disable()
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +00001369
Guido van Rossumd8faa362007-04-27 19:54:29 +00001370if __name__ == "__main__":
1371 test_main()