blob: 18f8d10c5ba6ac6a106c12d85c0c915184b296db [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
Pablo Galindoa2ec3f02020-01-14 12:06:45 +0000589 def test_is_finalized(self):
590 # Objects not tracked by the always gc return false
591 self.assertFalse(gc.is_finalized(3))
592
593 storage = []
594 class Lazarus:
595 def __del__(self):
596 storage.append(self)
597
598 lazarus = Lazarus()
599 self.assertFalse(gc.is_finalized(lazarus))
600
601 del lazarus
602 gc.collect()
603
604 lazarus = storage.pop()
605 self.assertTrue(gc.is_finalized(lazarus))
606
Guido van Rossumd8faa362007-04-27 19:54:29 +0000607 def test_bug1055820b(self):
608 # Corresponds to temp2b.py in the bug report.
609
610 ouch = []
611 def callback(ignored):
612 ouch[:] = [wr() for wr in WRs]
613
614 Cs = [C1055820(i) for i in range(2)]
615 WRs = [weakref.ref(c, callback) for c in Cs]
616 c = None
617
618 gc.collect()
619 self.assertEqual(len(ouch), 0)
620 # Make the two instances trash, and collect again. The bug was that
621 # the callback materialized a strong reference to an instance, but gc
622 # cleared the instance's dict anyway.
623 Cs = None
624 gc.collect()
625 self.assertEqual(len(ouch), 2) # else the callbacks didn't run
626 for x in ouch:
627 # If the callback resurrected one of these guys, the instance
628 # would be damaged, with an empty __dict__.
629 self.assertEqual(x, None)
630
Tim Peters5fbc7b12014-05-08 17:42:19 -0500631 def test_bug21435(self):
632 # This is a poor test - its only virtue is that it happened to
633 # segfault on Tim's Windows box before the patch for 21435 was
634 # applied. That's a nasty bug relying on specific pieces of cyclic
635 # trash appearing in exactly the right order in finalize_garbage()'s
636 # input list.
637 # But there's no reliable way to force that order from Python code,
638 # so over time chances are good this test won't really be testing much
639 # of anything anymore. Still, if it blows up, there's _some_
640 # problem ;-)
641 gc.collect()
642
643 class A:
644 pass
645
646 class B:
647 def __init__(self, x):
648 self.x = x
649
650 def __del__(self):
651 self.attr = None
652
653 def do_work():
654 a = A()
655 b = B(A())
656
657 a.attr = b
658 b.attr = a
659
660 do_work()
661 gc.collect() # this blows up (bad C pointer) when it fails
662
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200663 @cpython_only
Antoine Pitrou696e0352010-08-08 22:18:46 +0000664 def test_garbage_at_shutdown(self):
665 import subprocess
666 code = """if 1:
667 import gc
Antoine Pitrou796564c2013-07-30 19:59:21 +0200668 import _testcapi
669 @_testcapi.with_tp_del
Antoine Pitrou696e0352010-08-08 22:18:46 +0000670 class X:
671 def __init__(self, name):
672 self.name = name
673 def __repr__(self):
674 return "<X %%r>" %% self.name
Antoine Pitrou796564c2013-07-30 19:59:21 +0200675 def __tp_del__(self):
Antoine Pitrou696e0352010-08-08 22:18:46 +0000676 pass
677
678 x = X('first')
679 x.x = x
680 x.y = X('second')
681 del x
Antoine Pitrou2ed94eb2010-09-14 09:48:39 +0000682 gc.set_debug(%s)
Antoine Pitrou696e0352010-08-08 22:18:46 +0000683 """
684 def run_command(code):
Georg Brandl08be72d2010-10-24 15:11:22 +0000685 p = subprocess.Popen([sys.executable, "-Wd", "-c", code],
Antoine Pitrou696e0352010-08-08 22:18:46 +0000686 stdout=subprocess.PIPE,
687 stderr=subprocess.PIPE)
688 stdout, stderr = p.communicate()
Brian Curtin8291af22010-11-01 16:40:17 +0000689 p.stdout.close()
690 p.stderr.close()
Antoine Pitrou696e0352010-08-08 22:18:46 +0000691 self.assertEqual(p.returncode, 0)
Victor Stinner6cac1132019-12-08 08:38:16 +0100692 self.assertEqual(stdout, b"")
693 return stderr
Antoine Pitrou696e0352010-08-08 22:18:46 +0000694
Antoine Pitrou2ed94eb2010-09-14 09:48:39 +0000695 stderr = run_command(code % "0")
Georg Brandl08be72d2010-10-24 15:11:22 +0000696 self.assertIn(b"ResourceWarning: gc: 2 uncollectable objects at "
697 b"shutdown; use", stderr)
Antoine Pitrouaee47562010-09-16 15:04:49 +0000698 self.assertNotIn(b"<X 'first'>", stderr)
Antoine Pitrou696e0352010-08-08 22:18:46 +0000699 # With DEBUG_UNCOLLECTABLE, the garbage list gets printed
Antoine Pitrou2ed94eb2010-09-14 09:48:39 +0000700 stderr = run_command(code % "gc.DEBUG_UNCOLLECTABLE")
Georg Brandl08be72d2010-10-24 15:11:22 +0000701 self.assertIn(b"ResourceWarning: gc: 2 uncollectable objects at "
702 b"shutdown", stderr)
Antoine Pitrouaee47562010-09-16 15:04:49 +0000703 self.assertTrue(
704 (b"[<X 'first'>, <X 'second'>]" in stderr) or
705 (b"[<X 'second'>, <X 'first'>]" in stderr), stderr)
Antoine Pitrou2ed94eb2010-09-14 09:48:39 +0000706 # With DEBUG_SAVEALL, no additional message should get printed
707 # (because gc.garbage also contains normally reclaimable cyclic
708 # references, and its elements get printed at runtime anyway).
709 stderr = run_command(code % "gc.DEBUG_SAVEALL")
710 self.assertNotIn(b"uncollectable objects at shutdown", stderr)
711
Serhiy Storchakaa7930372016-07-03 22:27:26 +0300712 @requires_type_collecting
Antoine Pitrou5f454a02013-05-06 21:15:57 +0200713 def test_gc_main_module_at_shutdown(self):
714 # Create a reference cycle through the __main__ module and check
715 # it gets collected at interpreter shutdown.
716 code = """if 1:
Antoine Pitrou5f454a02013-05-06 21:15:57 +0200717 class C:
718 def __del__(self):
719 print('__del__ called')
720 l = [C()]
721 l.append(l)
722 """
723 rc, out, err = assert_python_ok('-c', code)
724 self.assertEqual(out.strip(), b'__del__ called')
725
Serhiy Storchakaa7930372016-07-03 22:27:26 +0300726 @requires_type_collecting
Antoine Pitrou5f454a02013-05-06 21:15:57 +0200727 def test_gc_ordinary_module_at_shutdown(self):
728 # Same as above, but with a non-__main__ module.
729 with temp_dir() as script_dir:
730 module = """if 1:
Antoine Pitrou5f454a02013-05-06 21:15:57 +0200731 class C:
732 def __del__(self):
733 print('__del__ called')
734 l = [C()]
735 l.append(l)
736 """
737 code = """if 1:
738 import sys
739 sys.path.insert(0, %r)
740 import gctest
741 """ % (script_dir,)
742 make_script(script_dir, 'gctest', module)
743 rc, out, err = assert_python_ok('-c', code)
744 self.assertEqual(out.strip(), b'__del__ called')
745
Zackery Spytzd8cba5d2018-07-03 13:47:22 -0600746 @requires_type_collecting
747 def test_global_del_SystemExit(self):
748 code = """if 1:
749 class ClassWithDel:
750 def __del__(self):
751 print('__del__ called')
752 a = ClassWithDel()
753 a.link = a
754 raise SystemExit(0)"""
755 self.addCleanup(unlink, TESTFN)
756 with open(TESTFN, 'w') as script:
757 script.write(code)
758 rc, out, err = assert_python_ok(TESTFN)
759 self.assertEqual(out.strip(), b'__del__ called')
760
Antoine Pitroud4156c12012-10-30 22:43:19 +0100761 def test_get_stats(self):
762 stats = gc.get_stats()
763 self.assertEqual(len(stats), 3)
764 for st in stats:
765 self.assertIsInstance(st, dict)
766 self.assertEqual(set(st),
767 {"collected", "collections", "uncollectable"})
768 self.assertGreaterEqual(st["collected"], 0)
769 self.assertGreaterEqual(st["collections"], 0)
770 self.assertGreaterEqual(st["uncollectable"], 0)
771 # Check that collection counts are incremented correctly
772 if gc.isenabled():
773 self.addCleanup(gc.enable)
774 gc.disable()
775 old = gc.get_stats()
776 gc.collect(0)
777 new = gc.get_stats()
778 self.assertEqual(new[0]["collections"], old[0]["collections"] + 1)
779 self.assertEqual(new[1]["collections"], old[1]["collections"])
780 self.assertEqual(new[2]["collections"], old[2]["collections"])
781 gc.collect(2)
782 new = gc.get_stats()
783 self.assertEqual(new[0]["collections"], old[0]["collections"] + 1)
784 self.assertEqual(new[1]["collections"], old[1]["collections"])
785 self.assertEqual(new[2]["collections"], old[2]["collections"] + 1)
786
brainfvckc75edab2017-10-16 12:49:41 -0700787 def test_freeze(self):
788 gc.freeze()
789 self.assertGreater(gc.get_freeze_count(), 0)
790 gc.unfreeze()
791 self.assertEqual(gc.get_freeze_count(), 0)
792
Pablo Galindo175421b2019-02-23 03:02:06 +0000793 def test_get_objects(self):
794 gc.collect()
795 l = []
796 l.append(l)
Pablo Galindod60a79a2019-03-01 01:12:27 -0800797 self.assertTrue(
798 any(l is element for element in gc.get_objects(generation=0))
799 )
800 self.assertFalse(
801 any(l is element for element in gc.get_objects(generation=1))
802 )
803 self.assertFalse(
804 any(l is element for element in gc.get_objects(generation=2))
805 )
Pablo Galindo175421b2019-02-23 03:02:06 +0000806 gc.collect(generation=0)
Pablo Galindod60a79a2019-03-01 01:12:27 -0800807 self.assertFalse(
808 any(l is element for element in gc.get_objects(generation=0))
809 )
810 self.assertTrue(
811 any(l is element for element in gc.get_objects(generation=1))
812 )
813 self.assertFalse(
814 any(l is element for element in gc.get_objects(generation=2))
815 )
Pablo Galindo175421b2019-02-23 03:02:06 +0000816 gc.collect(generation=1)
Pablo Galindod60a79a2019-03-01 01:12:27 -0800817 self.assertFalse(
818 any(l is element for element in gc.get_objects(generation=0))
819 )
820 self.assertFalse(
821 any(l is element for element in gc.get_objects(generation=1))
822 )
823 self.assertTrue(
824 any(l is element for element in gc.get_objects(generation=2))
825 )
Pablo Galindo175421b2019-02-23 03:02:06 +0000826 gc.collect(generation=2)
Pablo Galindod60a79a2019-03-01 01:12:27 -0800827 self.assertFalse(
828 any(l is element for element in gc.get_objects(generation=0))
829 )
830 self.assertFalse(
831 any(l is element for element in gc.get_objects(generation=1))
832 )
833 self.assertTrue(
834 any(l is element for element in gc.get_objects(generation=2))
835 )
Pablo Galindo175421b2019-02-23 03:02:06 +0000836 del l
837 gc.collect()
838
839 def test_get_objects_arguments(self):
840 gc.collect()
841 self.assertEqual(len(gc.get_objects()),
842 len(gc.get_objects(generation=None)))
843
844 self.assertRaises(ValueError, gc.get_objects, 1000)
845 self.assertRaises(ValueError, gc.get_objects, -1000)
846 self.assertRaises(TypeError, gc.get_objects, "1")
847 self.assertRaises(TypeError, gc.get_objects, 1.234)
848
Pablo Galindo466326d2019-10-13 16:48:59 +0100849 def test_resurrection_only_happens_once_per_object(self):
850 class A: # simple self-loop
851 def __init__(self):
852 self.me = self
853
854 class Lazarus(A):
855 resurrected = 0
856 resurrected_instances = []
857
858 def __del__(self):
859 Lazarus.resurrected += 1
860 Lazarus.resurrected_instances.append(self)
861
862 gc.collect()
863 gc.disable()
864
865 # We start with 0 resurrections
866 laz = Lazarus()
867 self.assertEqual(Lazarus.resurrected, 0)
868
869 # Deleting the instance and triggering a collection
870 # resurrects the object
871 del laz
872 gc.collect()
873 self.assertEqual(Lazarus.resurrected, 1)
874 self.assertEqual(len(Lazarus.resurrected_instances), 1)
875
876 # Clearing the references and forcing a collection
877 # should not resurrect the object again.
878 Lazarus.resurrected_instances.clear()
879 self.assertEqual(Lazarus.resurrected, 1)
880 gc.collect()
881 self.assertEqual(Lazarus.resurrected, 1)
882
883 gc.enable()
884
885 def test_resurrection_is_transitive(self):
886 class Cargo:
887 def __init__(self):
888 self.me = self
889
890 class Lazarus:
891 resurrected_instances = []
892
893 def __del__(self):
894 Lazarus.resurrected_instances.append(self)
895
896 gc.collect()
897 gc.disable()
898
899 laz = Lazarus()
900 cargo = Cargo()
901 cargo_id = id(cargo)
902
903 # Create a cycle between cargo and laz
904 laz.cargo = cargo
905 cargo.laz = laz
906
907 # Drop the references, force a collection and check that
908 # everything was resurrected.
909 del laz, cargo
910 gc.collect()
911 self.assertEqual(len(Lazarus.resurrected_instances), 1)
912 instance = Lazarus.resurrected_instances.pop()
913 self.assertTrue(hasattr(instance, "cargo"))
914 self.assertEqual(id(instance.cargo), cargo_id)
915
916 gc.collect()
917 gc.enable()
918
919 def test_resurrection_does_not_block_cleanup_of_other_objects(self):
920
Tim Petersecbf35f2019-10-09 12:37:30 -0500921 # When a finalizer resurrects objects, stats were reporting them as
922 # having been collected. This affected both collect()'s return
923 # value and the dicts returned by get_stats().
924 N = 100
925
926 class A: # simple self-loop
927 def __init__(self):
928 self.me = self
929
930 class Z(A): # resurrecting __del__
931 def __del__(self):
932 zs.append(self)
933
934 zs = []
935
936 def getstats():
937 d = gc.get_stats()[-1]
938 return d['collected'], d['uncollectable']
939
940 gc.collect()
941 gc.disable()
942
943 # No problems if just collecting A() instances.
944 oldc, oldnc = getstats()
945 for i in range(N):
946 A()
947 t = gc.collect()
948 c, nc = getstats()
949 self.assertEqual(t, 2*N) # instance object & its dict
950 self.assertEqual(c - oldc, 2*N)
951 self.assertEqual(nc - oldnc, 0)
952
953 # But Z() is not actually collected.
954 oldc, oldnc = c, nc
955 Z()
956 # Nothing is collected - Z() is merely resurrected.
957 t = gc.collect()
958 c, nc = getstats()
Pablo Galindo466326d2019-10-13 16:48:59 +0100959 self.assertEqual(t, 0)
960 self.assertEqual(c - oldc, 0)
Tim Petersecbf35f2019-10-09 12:37:30 -0500961 self.assertEqual(nc - oldnc, 0)
962
Pablo Galindo466326d2019-10-13 16:48:59 +0100963 # Z() should not prevent anything else from being collected.
Tim Petersecbf35f2019-10-09 12:37:30 -0500964 oldc, oldnc = c, nc
965 for i in range(N):
966 A()
967 Z()
Tim Petersecbf35f2019-10-09 12:37:30 -0500968 t = gc.collect()
969 c, nc = getstats()
970 self.assertEqual(t, 2*N)
971 self.assertEqual(c - oldc, 2*N)
972 self.assertEqual(nc - oldnc, 0)
973
Pablo Galindo466326d2019-10-13 16:48:59 +0100974 # The A() trash should have been reclaimed already but the
975 # 2 copies of Z are still in zs (and the associated dicts).
976 oldc, oldnc = c, nc
977 zs.clear()
978 t = gc.collect()
979 c, nc = getstats()
980 self.assertEqual(t, 4)
981 self.assertEqual(c - oldc, 4)
982 self.assertEqual(nc - oldnc, 0)
983
Tim Petersecbf35f2019-10-09 12:37:30 -0500984 gc.enable()
Antoine Pitrou696e0352010-08-08 22:18:46 +0000985
Neil Schemenauer392a13b2019-10-15 20:56:48 -0700986 @unittest.skipIf(ContainerNoGC is None,
987 'requires ContainerNoGC extension type')
988 def test_trash_weakref_clear(self):
989 # Test that trash weakrefs are properly cleared (bpo-38006).
990 #
991 # Structure we are creating:
992 #
993 # Z <- Y <- A--+--> WZ -> C
994 # ^ |
995 # +--+
996 # where:
997 # WZ is a weakref to Z with callback C
998 # Y doesn't implement tp_traverse
999 # A contains a reference to itself, Y and WZ
1000 #
1001 # A, Y, Z, WZ are all trash. The GC doesn't know that Z is trash
1002 # because Y does not implement tp_traverse. To show the bug, WZ needs
1003 # to live long enough so that Z is deallocated before it. Then, if
1004 # gcmodule is buggy, when Z is being deallocated, C will run.
1005 #
1006 # To ensure WZ lives long enough, we put it in a second reference
1007 # cycle. That trick only works due to the ordering of the GC prev/next
1008 # linked lists. So, this test is a bit fragile.
1009 #
1010 # The bug reported in bpo-38006 is caused because the GC did not
1011 # clear WZ before starting the process of calling tp_clear on the
1012 # trash. Normally, handle_weakrefs() would find the weakref via Z and
1013 # clear it. However, since the GC cannot find Z, WR is not cleared and
1014 # it can execute during delete_garbage(). That can lead to disaster
1015 # since the callback might tinker with objects that have already had
1016 # tp_clear called on them (leaving them in possibly invalid states).
1017
1018 callback = unittest.mock.Mock()
1019
1020 class A:
1021 __slots__ = ['a', 'y', 'wz']
1022
1023 class Z:
1024 pass
1025
1026 # setup required object graph, as described above
1027 a = A()
1028 a.a = a
1029 a.y = ContainerNoGC(Z())
1030 a.wz = weakref.ref(a.y.value, callback)
1031 # create second cycle to keep WZ alive longer
1032 wr_cycle = [a.wz]
1033 wr_cycle.append(wr_cycle)
1034 # ensure trash unrelated to this test is gone
1035 gc.collect()
1036 gc.disable()
1037 # release references and create trash
1038 del a, wr_cycle
1039 gc.collect()
1040 # if called, it means there is a bug in the GC. The weakref should be
1041 # cleared before Z dies.
1042 callback.assert_not_called()
1043 gc.enable()
1044
1045
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +00001046class GCCallbackTests(unittest.TestCase):
1047 def setUp(self):
1048 # Save gc state and disable it.
1049 self.enabled = gc.isenabled()
1050 gc.disable()
1051 self.debug = gc.get_debug()
1052 gc.set_debug(0)
1053 gc.callbacks.append(self.cb1)
1054 gc.callbacks.append(self.cb2)
Antoine Pitrou6b64fc62012-04-16 21:29:02 +02001055 self.othergarbage = []
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +00001056
1057 def tearDown(self):
1058 # Restore gc state
1059 del self.visit
1060 gc.callbacks.remove(self.cb1)
1061 gc.callbacks.remove(self.cb2)
1062 gc.set_debug(self.debug)
1063 if self.enabled:
1064 gc.enable()
1065 # destroy any uncollectables
1066 gc.collect()
1067 for obj in gc.garbage:
1068 if isinstance(obj, Uncollectable):
1069 obj.partner = None
1070 del gc.garbage[:]
Antoine Pitrou6b64fc62012-04-16 21:29:02 +02001071 del self.othergarbage
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +00001072 gc.collect()
1073
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +00001074 def preclean(self):
1075 # Remove all fluff from the system. Invoke this function
1076 # manually rather than through self.setUp() for maximum
1077 # safety.
1078 self.visit = []
1079 gc.collect()
1080 garbage, gc.garbage[:] = gc.garbage[:], []
1081 self.othergarbage.append(garbage)
1082 self.visit = []
1083
1084 def cb1(self, phase, info):
1085 self.visit.append((1, phase, dict(info)))
1086
1087 def cb2(self, phase, info):
1088 self.visit.append((2, phase, dict(info)))
1089 if phase == "stop" and hasattr(self, "cleanup"):
1090 # Clean Uncollectable from garbage
1091 uc = [e for e in gc.garbage if isinstance(e, Uncollectable)]
1092 gc.garbage[:] = [e for e in gc.garbage
1093 if not isinstance(e, Uncollectable)]
1094 for e in uc:
1095 e.partner = None
1096
Antoine Pitroude3c73b2012-04-16 21:29:58 +02001097 def test_collect(self):
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +00001098 self.preclean()
1099 gc.collect()
1100 # Algorithmically verify the contents of self.visit
1101 # because it is long and tortuous.
1102
1103 # Count the number of visits to each callback
1104 n = [v[0] for v in self.visit]
1105 n1 = [i for i in n if i == 1]
1106 n2 = [i for i in n if i == 2]
1107 self.assertEqual(n1, [1]*2)
1108 self.assertEqual(n2, [2]*2)
1109
1110 # Count that we got the right number of start and stop callbacks.
1111 n = [v[1] for v in self.visit]
1112 n1 = [i for i in n if i == "start"]
1113 n2 = [i for i in n if i == "stop"]
1114 self.assertEqual(n1, ["start"]*2)
1115 self.assertEqual(n2, ["stop"]*2)
1116
1117 # Check that we got the right info dict for all callbacks
1118 for v in self.visit:
1119 info = v[2]
1120 self.assertTrue("generation" in info)
1121 self.assertTrue("collected" in info)
1122 self.assertTrue("uncollectable" in info)
1123
Antoine Pitroude3c73b2012-04-16 21:29:58 +02001124 def test_collect_generation(self):
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +00001125 self.preclean()
1126 gc.collect(2)
1127 for v in self.visit:
1128 info = v[2]
1129 self.assertEqual(info["generation"], 2)
1130
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001131 @cpython_only
Antoine Pitroude3c73b2012-04-16 21:29:58 +02001132 def test_collect_garbage(self):
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +00001133 self.preclean()
1134 # Each of these cause four objects to be garbage: Two
Min ho Kim39d87b52019-08-31 06:21:19 +10001135 # Uncollectables and their instance dicts.
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +00001136 Uncollectable()
1137 Uncollectable()
1138 C1055820(666)
1139 gc.collect()
1140 for v in self.visit:
1141 if v[1] != "stop":
1142 continue
1143 info = v[2]
1144 self.assertEqual(info["collected"], 2)
1145 self.assertEqual(info["uncollectable"], 8)
1146
1147 # We should now have the Uncollectables in gc.garbage
1148 self.assertEqual(len(gc.garbage), 4)
1149 for e in gc.garbage:
1150 self.assertIsInstance(e, Uncollectable)
1151
1152 # Now, let our callback handle the Uncollectable instances
1153 self.cleanup=True
1154 self.visit = []
1155 gc.garbage[:] = []
1156 gc.collect()
1157 for v in self.visit:
1158 if v[1] != "stop":
1159 continue
1160 info = v[2]
1161 self.assertEqual(info["collected"], 0)
1162 self.assertEqual(info["uncollectable"], 4)
1163
1164 # Uncollectables should be gone
1165 self.assertEqual(len(gc.garbage), 0)
1166
1167
Victor Stinner626bff82018-10-25 17:31:10 +02001168 @unittest.skipIf(BUILD_WITH_NDEBUG,
1169 'built with -NDEBUG')
1170 def test_refcount_errors(self):
1171 self.preclean()
1172 # Verify the "handling" of objects with broken refcounts
1173
1174 # Skip the test if ctypes is not available
1175 import_module("ctypes")
1176
1177 import subprocess
1178 code = textwrap.dedent('''
1179 from test.support import gc_collect, SuppressCrashReport
1180
1181 a = [1, 2, 3]
1182 b = [a]
1183
1184 # Avoid coredump when Py_FatalError() calls abort()
1185 SuppressCrashReport().__enter__()
1186
1187 # Simulate the refcount of "a" being too low (compared to the
1188 # references held on it by live data), but keeping it above zero
1189 # (to avoid deallocating it):
1190 import ctypes
1191 ctypes.pythonapi.Py_DecRef(ctypes.py_object(a))
1192
1193 # The garbage collector should now have a fatal error
1194 # when it reaches the broken object
1195 gc_collect()
1196 ''')
1197 p = subprocess.Popen([sys.executable, "-c", code],
1198 stdout=subprocess.PIPE,
1199 stderr=subprocess.PIPE)
1200 stdout, stderr = p.communicate()
1201 p.stdout.close()
1202 p.stderr.close()
1203 # Verify that stderr has a useful error message:
1204 self.assertRegex(stderr,
1205 br'gcmodule\.c:[0-9]+: gc_decref: Assertion "gc_get_refs\(g\) > 0" failed.')
1206 self.assertRegex(stderr,
1207 br'refcount is too small')
Victor Stinner626bff82018-10-25 17:31:10 +02001208 # "address : 0x7fb5062efc18"
1209 # "address : 7FB5062EFC18"
Victor Stinner68762572019-10-07 18:42:01 +02001210 address_regex = br'[0-9a-fA-Fx]+'
Victor Stinner626bff82018-10-25 17:31:10 +02001211 self.assertRegex(stderr,
Victor Stinner68762572019-10-07 18:42:01 +02001212 br'object address : ' + address_regex)
1213 self.assertRegex(stderr,
1214 br'object refcount : 1')
1215 self.assertRegex(stderr,
1216 br'object type : ' + address_regex)
1217 self.assertRegex(stderr,
1218 br'object type name: list')
1219 self.assertRegex(stderr,
1220 br'object repr : \[1, 2, 3\]')
Victor Stinner626bff82018-10-25 17:31:10 +02001221
1222
Guido van Rossumd8faa362007-04-27 19:54:29 +00001223class GCTogglingTests(unittest.TestCase):
1224 def setUp(self):
1225 gc.enable()
1226
1227 def tearDown(self):
1228 gc.disable()
1229
1230 def test_bug1055820c(self):
1231 # Corresponds to temp2c.py in the bug report. This is pretty
1232 # elaborate.
1233
1234 c0 = C1055820(0)
1235 # Move c0 into generation 2.
1236 gc.collect()
1237
1238 c1 = C1055820(1)
1239 c1.keep_c0_alive = c0
1240 del c0.loop # now only c1 keeps c0 alive
1241
1242 c2 = C1055820(2)
1243 c2wr = weakref.ref(c2) # no callback!
1244
1245 ouch = []
1246 def callback(ignored):
Tim Petersead8b7a2004-10-30 23:09:22 +00001247 ouch[:] = [c2wr()]
1248
Guido van Rossumd8faa362007-04-27 19:54:29 +00001249 # The callback gets associated with a wr on an object in generation 2.
1250 c0wr = weakref.ref(c0, callback)
Tim Petersead8b7a2004-10-30 23:09:22 +00001251
Guido van Rossumd8faa362007-04-27 19:54:29 +00001252 c0 = c1 = c2 = None
Tim Petersead8b7a2004-10-30 23:09:22 +00001253
Guido van Rossumd8faa362007-04-27 19:54:29 +00001254 # What we've set up: c0, c1, and c2 are all trash now. c0 is in
1255 # generation 2. The only thing keeping it alive is that c1 points to
1256 # it. c1 and c2 are in generation 0, and are in self-loops. There's a
1257 # global weakref to c2 (c2wr), but that weakref has no callback.
1258 # There's also a global weakref to c0 (c0wr), and that does have a
1259 # callback, and that callback references c2 via c2wr().
1260 #
1261 # c0 has a wr with callback, which references c2wr
1262 # ^
1263 # |
1264 # | Generation 2 above dots
1265 #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . .
1266 # | Generation 0 below dots
1267 # |
1268 # |
1269 # ^->c1 ^->c2 has a wr but no callback
1270 # | | | |
1271 # <--v <--v
1272 #
1273 # So this is the nightmare: when generation 0 gets collected, we see
1274 # that c2 has a callback-free weakref, and c1 doesn't even have a
1275 # weakref. Collecting generation 0 doesn't see c0 at all, and c0 is
1276 # the only object that has a weakref with a callback. gc clears c1
1277 # and c2. Clearing c1 has the side effect of dropping the refcount on
1278 # c0 to 0, so c0 goes away (despite that it's in an older generation)
1279 # and c0's wr callback triggers. That in turn materializes a reference
1280 # to c2 via c2wr(), but c2 gets cleared anyway by gc.
Tim Petersead8b7a2004-10-30 23:09:22 +00001281
Guido van Rossumd8faa362007-04-27 19:54:29 +00001282 # We want to let gc happen "naturally", to preserve the distinction
1283 # between generations.
1284 junk = []
1285 i = 0
1286 detector = GC_Detector()
1287 while not detector.gc_happened:
1288 i += 1
1289 if i > 10000:
1290 self.fail("gc didn't happen after 10000 iterations")
1291 self.assertEqual(len(ouch), 0)
1292 junk.append([]) # this will eventually trigger gc
Tim Petersead8b7a2004-10-30 23:09:22 +00001293
Guido van Rossumd8faa362007-04-27 19:54:29 +00001294 self.assertEqual(len(ouch), 1) # else the callback wasn't invoked
1295 for x in ouch:
1296 # If the callback resurrected c2, the instance would be damaged,
1297 # with an empty __dict__.
1298 self.assertEqual(x, None)
Tim Petersead8b7a2004-10-30 23:09:22 +00001299
Guido van Rossumd8faa362007-04-27 19:54:29 +00001300 def test_bug1055820d(self):
1301 # Corresponds to temp2d.py in the bug report. This is very much like
1302 # test_bug1055820c, but uses a __del__ method instead of a weakref
1303 # callback to sneak in a resurrection of cyclic trash.
Tim Petersead8b7a2004-10-30 23:09:22 +00001304
Guido van Rossumd8faa362007-04-27 19:54:29 +00001305 ouch = []
1306 class D(C1055820):
1307 def __del__(self):
1308 ouch[:] = [c2wr()]
Tim Petersead8b7a2004-10-30 23:09:22 +00001309
Guido van Rossumd8faa362007-04-27 19:54:29 +00001310 d0 = D(0)
1311 # Move all the above into generation 2.
1312 gc.collect()
Tim Petersead8b7a2004-10-30 23:09:22 +00001313
Guido van Rossumd8faa362007-04-27 19:54:29 +00001314 c1 = C1055820(1)
1315 c1.keep_d0_alive = d0
1316 del d0.loop # now only c1 keeps d0 alive
Tim Petersead8b7a2004-10-30 23:09:22 +00001317
Guido van Rossumd8faa362007-04-27 19:54:29 +00001318 c2 = C1055820(2)
1319 c2wr = weakref.ref(c2) # no callback!
Tim Petersead8b7a2004-10-30 23:09:22 +00001320
Guido van Rossumd8faa362007-04-27 19:54:29 +00001321 d0 = c1 = c2 = None
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +00001322
Guido van Rossumd8faa362007-04-27 19:54:29 +00001323 # What we've set up: d0, c1, and c2 are all trash now. d0 is in
1324 # generation 2. The only thing keeping it alive is that c1 points to
1325 # it. c1 and c2 are in generation 0, and are in self-loops. There's
1326 # a global weakref to c2 (c2wr), but that weakref has no callback.
1327 # There are no other weakrefs.
1328 #
1329 # d0 has a __del__ method that references c2wr
1330 # ^
1331 # |
1332 # | Generation 2 above dots
1333 #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . .
1334 # | Generation 0 below dots
1335 # |
1336 # |
1337 # ^->c1 ^->c2 has a wr but no callback
1338 # | | | |
1339 # <--v <--v
1340 #
1341 # So this is the nightmare: when generation 0 gets collected, we see
1342 # that c2 has a callback-free weakref, and c1 doesn't even have a
1343 # weakref. Collecting generation 0 doesn't see d0 at all. gc clears
1344 # c1 and c2. Clearing c1 has the side effect of dropping the refcount
1345 # on d0 to 0, so d0 goes away (despite that it's in an older
1346 # generation) and d0's __del__ triggers. That in turn materializes
1347 # a reference to c2 via c2wr(), but c2 gets cleared anyway by gc.
1348
1349 # We want to let gc happen "naturally", to preserve the distinction
1350 # between generations.
1351 detector = GC_Detector()
1352 junk = []
1353 i = 0
1354 while not detector.gc_happened:
1355 i += 1
1356 if i > 10000:
1357 self.fail("gc didn't happen after 10000 iterations")
1358 self.assertEqual(len(ouch), 0)
1359 junk.append([]) # this will eventually trigger gc
1360
1361 self.assertEqual(len(ouch), 1) # else __del__ wasn't invoked
1362 for x in ouch:
1363 # If __del__ resurrected c2, the instance would be damaged, with an
1364 # empty __dict__.
1365 self.assertEqual(x, None)
1366
1367def test_main():
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +00001368 enabled = gc.isenabled()
1369 gc.disable()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001370 assert not gc.isenabled()
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001371 debug = gc.get_debug()
1372 gc.set_debug(debug & ~gc.DEBUG_LEAK) # this test is supposed to leak
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +00001373
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001374 try:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001375 gc.collect() # Delete 2nd generation garbage
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +00001376 run_unittest(GCTests, GCTogglingTests, GCCallbackTests)
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001377 finally:
1378 gc.set_debug(debug)
1379 # test gc.enable() even if GC is disabled by default
1380 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001381 print("restoring automatic collection")
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001382 # make sure to always test gc.enable()
1383 gc.enable()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001384 assert gc.isenabled()
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001385 if not enabled:
1386 gc.disable()
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +00001387
Guido van Rossumd8faa362007-04-27 19:54:29 +00001388if __name__ == "__main__":
1389 test_main()