blob: 246980aa74c2b844cc7477684ef71fddb0319d5c [file] [log] [blame]
Guido van Rossumd8faa362007-04-27 19:54:29 +00001import unittest
Brett Cannon7a540732011-02-22 03:04:06 +00002from test.support import (verbose, refcount_test, run_unittest,
Serhiy Storchakaa7930372016-07-03 22:27:26 +03003 strip_python_stderr, cpython_only, start_threads,
Pablo Galindo72a0d212018-01-29 20:37:09 +00004 temp_dir, requires_type_collecting,reap_threads)
Berker Peksagce643912015-05-06 06:33:17 +03005from test.support.script_helper import assert_python_ok, make_script
Antoine Pitrou5f454a02013-05-06 21:15:57 +02006
Neil Schemenauer88c761a2001-07-12 13:25:53 +00007import sys
Antoine Pitrou2b0218a2012-09-06 00:59:49 +02008import time
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +00009import gc
Tim Petersead8b7a2004-10-30 23:09:22 +000010import weakref
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020011import threading
Pablo Galindo72a0d212018-01-29 20:37:09 +000012import warnings
13
Antoine Pitrou2b0218a2012-09-06 00:59:49 +020014
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020015try:
16 from _testcapi import with_tp_del
17except ImportError:
18 def with_tp_del(cls):
19 class C(object):
20 def __new__(cls, *args, **kwargs):
21 raise TypeError('requires _testcapi.with_tp_del')
22 return C
23
Guido van Rossumd8faa362007-04-27 19:54:29 +000024### Support code
25###############################################################################
Tim Peters0f81ab62003-04-08 16:39:48 +000026
Tim Petersead8b7a2004-10-30 23:09:22 +000027# Bug 1055820 has several tests of longstanding bugs involving weakrefs and
28# cyclic gc.
29
30# An instance of C1055820 has a self-loop, so becomes cyclic trash when
31# unreachable.
32class C1055820(object):
33 def __init__(self, i):
34 self.i = i
35 self.loop = self
36
37class GC_Detector(object):
38 # Create an instance I. Then gc hasn't happened again so long as
39 # I.gc_happened is false.
40
41 def __init__(self):
42 self.gc_happened = False
43
44 def it_happened(ignored):
45 self.gc_happened = True
46
47 # Create a piece of cyclic trash that triggers it_happened when
48 # gc collects it.
49 self.wr = weakref.ref(C1055820(666), it_happened)
50
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020051@with_tp_del
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +000052class Uncollectable(object):
53 """Create a reference cycle with multiple __del__ methods.
54
55 An object in a reference cycle will never have zero references,
56 and so must be garbage collected. If one or more objects in the
57 cycle have __del__ methods, the gc refuses to guess an order,
58 and leaves the cycle uncollected."""
59 def __init__(self, partner=None):
60 if partner is None:
61 self.partner = Uncollectable(partner=self)
62 else:
63 self.partner = partner
Antoine Pitrou796564c2013-07-30 19:59:21 +020064 def __tp_del__(self):
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +000065 pass
Tim Petersead8b7a2004-10-30 23:09:22 +000066
Guido van Rossumd8faa362007-04-27 19:54:29 +000067### Tests
68###############################################################################
Tim Petersead8b7a2004-10-30 23:09:22 +000069
Guido van Rossumd8faa362007-04-27 19:54:29 +000070class GCTests(unittest.TestCase):
71 def test_list(self):
72 l = []
73 l.append(l)
74 gc.collect()
75 del l
76 self.assertEqual(gc.collect(), 1)
Tim Petersead8b7a2004-10-30 23:09:22 +000077
Guido van Rossumd8faa362007-04-27 19:54:29 +000078 def test_dict(self):
79 d = {}
80 d[1] = d
81 gc.collect()
82 del d
83 self.assertEqual(gc.collect(), 1)
Tim Petersead8b7a2004-10-30 23:09:22 +000084
Guido van Rossumd8faa362007-04-27 19:54:29 +000085 def test_tuple(self):
86 # since tuples are immutable we close the loop with a list
87 l = []
88 t = (l,)
89 l.append(t)
90 gc.collect()
91 del t
92 del l
93 self.assertEqual(gc.collect(), 2)
Tim Petersead8b7a2004-10-30 23:09:22 +000094
Guido van Rossumd8faa362007-04-27 19:54:29 +000095 def test_class(self):
96 class A:
97 pass
98 A.a = A
99 gc.collect()
100 del A
101 self.assertNotEqual(gc.collect(), 0)
Tim Petersead8b7a2004-10-30 23:09:22 +0000102
Guido van Rossumd8faa362007-04-27 19:54:29 +0000103 def test_newstyleclass(self):
104 class A(object):
105 pass
106 gc.collect()
107 del A
108 self.assertNotEqual(gc.collect(), 0)
Tim Petersead8b7a2004-10-30 23:09:22 +0000109
Guido van Rossumd8faa362007-04-27 19:54:29 +0000110 def test_instance(self):
111 class A:
112 pass
113 a = A()
114 a.a = a
115 gc.collect()
116 del a
117 self.assertNotEqual(gc.collect(), 0)
Tim Petersead8b7a2004-10-30 23:09:22 +0000118
Serhiy Storchakaa7930372016-07-03 22:27:26 +0300119 @requires_type_collecting
Guido van Rossumd8faa362007-04-27 19:54:29 +0000120 def test_newinstance(self):
121 class A(object):
122 pass
123 a = A()
124 a.a = a
125 gc.collect()
126 del a
127 self.assertNotEqual(gc.collect(), 0)
128 class B(list):
129 pass
130 class C(B, A):
131 pass
132 a = C()
133 a.a = a
134 gc.collect()
135 del a
136 self.assertNotEqual(gc.collect(), 0)
137 del B, C
138 self.assertNotEqual(gc.collect(), 0)
139 A.a = A()
140 del A
141 self.assertNotEqual(gc.collect(), 0)
142 self.assertEqual(gc.collect(), 0)
Tim Petersead8b7a2004-10-30 23:09:22 +0000143
Guido van Rossumd8faa362007-04-27 19:54:29 +0000144 def test_method(self):
145 # Tricky: self.__init__ is a bound method, it references the instance.
146 class A:
147 def __init__(self):
148 self.init = self.__init__
149 a = A()
150 gc.collect()
151 del a
152 self.assertNotEqual(gc.collect(), 0)
Tim Petersead8b7a2004-10-30 23:09:22 +0000153
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200154 @cpython_only
Antoine Pitrou796564c2013-07-30 19:59:21 +0200155 def test_legacy_finalizer(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000156 # A() is uncollectable if it is part of a cycle, make sure it shows up
157 # in gc.garbage.
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200158 @with_tp_del
Guido van Rossumd8faa362007-04-27 19:54:29 +0000159 class A:
Antoine Pitrou796564c2013-07-30 19:59:21 +0200160 def __tp_del__(self): pass
Guido van Rossumd8faa362007-04-27 19:54:29 +0000161 class B:
162 pass
163 a = A()
164 a.a = a
165 id_a = id(a)
166 b = B()
167 b.b = b
168 gc.collect()
169 del a
170 del b
171 self.assertNotEqual(gc.collect(), 0)
172 for obj in gc.garbage:
173 if id(obj) == id_a:
174 del obj.a
175 break
176 else:
177 self.fail("didn't find obj in garbage (finalizer)")
178 gc.garbage.remove(obj)
Tim Petersead8b7a2004-10-30 23:09:22 +0000179
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200180 @cpython_only
Antoine Pitrou796564c2013-07-30 19:59:21 +0200181 def test_legacy_finalizer_newclass(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000182 # A() is uncollectable if it is part of a cycle, make sure it shows up
183 # in gc.garbage.
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200184 @with_tp_del
Guido van Rossumd8faa362007-04-27 19:54:29 +0000185 class A(object):
Antoine Pitrou796564c2013-07-30 19:59:21 +0200186 def __tp_del__(self): pass
Guido van Rossumd8faa362007-04-27 19:54:29 +0000187 class B(object):
188 pass
189 a = A()
190 a.a = a
191 id_a = id(a)
192 b = B()
193 b.b = b
194 gc.collect()
195 del a
196 del b
197 self.assertNotEqual(gc.collect(), 0)
198 for obj in gc.garbage:
199 if id(obj) == id_a:
200 del obj.a
201 break
202 else:
203 self.fail("didn't find obj in garbage (finalizer)")
204 gc.garbage.remove(obj)
Tim Petersead8b7a2004-10-30 23:09:22 +0000205
Guido van Rossumd8faa362007-04-27 19:54:29 +0000206 def test_function(self):
207 # Tricky: f -> d -> f, code should call d.clear() after the exec to
208 # break the cycle.
209 d = {}
210 exec("def f(): pass\n", d)
211 gc.collect()
212 del d
213 self.assertEqual(gc.collect(), 2)
Tim Petersead8b7a2004-10-30 23:09:22 +0000214
Brett Cannon7a540732011-02-22 03:04:06 +0000215 @refcount_test
Guido van Rossumd8faa362007-04-27 19:54:29 +0000216 def test_frame(self):
217 def f():
218 frame = sys._getframe()
219 gc.collect()
220 f()
221 self.assertEqual(gc.collect(), 1)
Tim Petersead8b7a2004-10-30 23:09:22 +0000222
Guido van Rossumd8faa362007-04-27 19:54:29 +0000223 def test_saveall(self):
224 # Verify that cyclic garbage like lists show up in gc.garbage if the
225 # SAVEALL option is enabled.
Tim Petersead8b7a2004-10-30 23:09:22 +0000226
Guido van Rossumd8faa362007-04-27 19:54:29 +0000227 # First make sure we don't save away other stuff that just happens to
228 # be waiting for collection.
229 gc.collect()
230 # if this fails, someone else created immortal trash
231 self.assertEqual(gc.garbage, [])
232
233 L = []
234 L.append(L)
235 id_L = id(L)
236
237 debug = gc.get_debug()
238 gc.set_debug(debug | gc.DEBUG_SAVEALL)
239 del L
240 gc.collect()
241 gc.set_debug(debug)
242
243 self.assertEqual(len(gc.garbage), 1)
244 obj = gc.garbage.pop()
245 self.assertEqual(id(obj), id_L)
246
247 def test_del(self):
248 # __del__ methods can trigger collection, make this to happen
249 thresholds = gc.get_threshold()
250 gc.enable()
251 gc.set_threshold(1)
252
253 class A:
254 def __del__(self):
255 dir(self)
256 a = A()
257 del a
258
259 gc.disable()
260 gc.set_threshold(*thresholds)
261
262 def test_del_newclass(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(object):
269 def __del__(self):
270 dir(self)
271 a = A()
272 del a
273
274 gc.disable()
275 gc.set_threshold(*thresholds)
276
Christian Heimesa156e092008-02-16 07:38:31 +0000277 # The following two tests are fragile:
278 # They precisely count the number of allocations,
279 # which is highly implementation-dependent.
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200280 # For example, disposed tuples are not freed, but reused.
281 # To minimize variations, though, we first store the get_count() results
282 # and check them at the end.
Brett Cannon7a540732011-02-22 03:04:06 +0000283 @refcount_test
Guido van Rossumd8faa362007-04-27 19:54:29 +0000284 def test_get_count(self):
285 gc.collect()
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200286 a, b, c = gc.get_count()
287 x = []
288 d, e, f = gc.get_count()
289 self.assertEqual((b, c), (0, 0))
290 self.assertEqual((e, f), (0, 0))
291 # This is less fragile than asserting that a equals 0.
292 self.assertLess(a, 5)
293 # Between the two calls to get_count(), at least one object was
294 # created (the list).
295 self.assertGreater(d, a)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000296
Brett Cannon7a540732011-02-22 03:04:06 +0000297 @refcount_test
Guido van Rossumd8faa362007-04-27 19:54:29 +0000298 def test_collect_generations(self):
299 gc.collect()
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200300 # This object will "trickle" into generation N + 1 after
301 # each call to collect(N)
302 x = []
Guido van Rossumd8faa362007-04-27 19:54:29 +0000303 gc.collect(0)
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200304 # x is now in gen 1
305 a, b, c = gc.get_count()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000306 gc.collect(1)
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200307 # x is now in gen 2
308 d, e, f = gc.get_count()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000309 gc.collect(2)
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200310 # x is now in gen 3
311 g, h, i = gc.get_count()
312 # We don't check a, d, g since their exact values depends on
313 # internal implementation details of the interpreter.
314 self.assertEqual((b, c), (1, 0))
315 self.assertEqual((e, f), (0, 1))
316 self.assertEqual((h, i), (0, 0))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000317
318 def test_trashcan(self):
319 class Ouch:
320 n = 0
321 def __del__(self):
322 Ouch.n = Ouch.n + 1
323 if Ouch.n % 17 == 0:
324 gc.collect()
325
326 # "trashcan" is a hack to prevent stack overflow when deallocating
327 # very deeply nested tuples etc. It works in part by abusing the
328 # type pointer and refcount fields, and that can yield horrible
329 # problems when gc tries to traverse the structures.
330 # If this test fails (as it does in 2.0, 2.1 and 2.2), it will
331 # most likely die via segfault.
332
333 # Note: In 2.3 the possibility for compiling without cyclic gc was
334 # removed, and that in turn allows the trashcan mechanism to work
335 # via much simpler means (e.g., it never abuses the type pointer or
336 # refcount fields anymore). Since it's much less likely to cause a
337 # problem now, the various constants in this expensive (we force a lot
338 # of full collections) test are cut back from the 2.2 version.
339 gc.enable()
340 N = 150
341 for count in range(2):
342 t = []
343 for i in range(N):
344 t = [t, Ouch()]
345 u = []
346 for i in range(N):
347 u = [u, Ouch()]
348 v = {}
349 for i in range(N):
350 v = {1: v, 2: Ouch()}
351 gc.disable()
352
Antoine Pitrou2b0218a2012-09-06 00:59:49 +0200353 def test_trashcan_threads(self):
354 # Issue #13992: trashcan mechanism should be thread-safe
355 NESTING = 60
356 N_THREADS = 2
357
358 def sleeper_gen():
359 """A generator that releases the GIL when closed or dealloc'ed."""
360 try:
361 yield
362 finally:
363 time.sleep(0.000001)
364
365 class C(list):
366 # Appending to a list is atomic, which avoids the use of a lock.
367 inits = []
368 dels = []
369 def __init__(self, alist):
370 self[:] = alist
371 C.inits.append(None)
372 def __del__(self):
373 # This __del__ is called by subtype_dealloc().
374 C.dels.append(None)
375 # `g` will release the GIL when garbage-collected. This
376 # helps assert subtype_dealloc's behaviour when threads
377 # switch in the middle of it.
378 g = sleeper_gen()
379 next(g)
380 # Now that __del__ is finished, subtype_dealloc will proceed
381 # to call list_dealloc, which also uses the trashcan mechanism.
382
383 def make_nested():
384 """Create a sufficiently nested container object so that the
385 trashcan mechanism is invoked when deallocating it."""
386 x = C([])
387 for i in range(NESTING):
388 x = [C([x])]
389 del x
390
391 def run_thread():
392 """Exercise make_nested() in a loop."""
393 while not exit:
394 make_nested()
395
396 old_switchinterval = sys.getswitchinterval()
397 sys.setswitchinterval(1e-5)
398 try:
Serhiy Storchaka263dcd22015-04-01 13:01:14 +0300399 exit = []
Antoine Pitrou2b0218a2012-09-06 00:59:49 +0200400 threads = []
401 for i in range(N_THREADS):
402 t = threading.Thread(target=run_thread)
403 threads.append(t)
Serhiy Storchaka263dcd22015-04-01 13:01:14 +0300404 with start_threads(threads, lambda: exit.append(1)):
Serhiy Storchaka9db55002015-03-28 20:38:37 +0200405 time.sleep(1.0)
Antoine Pitrou2b0218a2012-09-06 00:59:49 +0200406 finally:
407 sys.setswitchinterval(old_switchinterval)
408 gc.collect()
409 self.assertEqual(len(C.inits), len(C.dels))
410
Guido van Rossumd8faa362007-04-27 19:54:29 +0000411 def test_boom(self):
412 class Boom:
413 def __getattr__(self, someattribute):
414 del self.attr
415 raise AttributeError
416
417 a = Boom()
418 b = Boom()
419 a.attr = b
420 b.attr = a
421
422 gc.collect()
423 garbagelen = len(gc.garbage)
424 del a, b
425 # a<->b are in a trash cycle now. Collection will invoke
426 # Boom.__getattr__ (to see whether a and b have __del__ methods), and
427 # __getattr__ deletes the internal "attr" attributes as a side effect.
428 # That causes the trash cycle to get reclaimed via refcounts falling to
429 # 0, thus mutating the trash graph as a side effect of merely asking
430 # whether __del__ exists. This used to (before 2.3b1) crash Python.
431 # Now __getattr__ isn't called.
432 self.assertEqual(gc.collect(), 4)
433 self.assertEqual(len(gc.garbage), garbagelen)
434
435 def test_boom2(self):
436 class Boom2:
437 def __init__(self):
438 self.x = 0
439
440 def __getattr__(self, someattribute):
441 self.x += 1
442 if self.x > 1:
443 del self.attr
444 raise AttributeError
445
446 a = Boom2()
447 b = Boom2()
448 a.attr = b
449 b.attr = a
450
451 gc.collect()
452 garbagelen = len(gc.garbage)
453 del a, b
454 # Much like test_boom(), except that __getattr__ doesn't break the
455 # cycle until the second time gc checks for __del__. As of 2.3b1,
456 # there isn't a second time, so this simply cleans up the trash cycle.
457 # We expect a, b, a.__dict__ and b.__dict__ (4 objects) to get
458 # reclaimed this way.
459 self.assertEqual(gc.collect(), 4)
460 self.assertEqual(len(gc.garbage), garbagelen)
461
462 def test_boom_new(self):
463 # boom__new and boom2_new are exactly like boom and boom2, except use
464 # new-style classes.
465
466 class Boom_New(object):
467 def __getattr__(self, someattribute):
468 del self.attr
469 raise AttributeError
470
471 a = Boom_New()
472 b = Boom_New()
473 a.attr = b
474 b.attr = a
475
476 gc.collect()
477 garbagelen = len(gc.garbage)
478 del a, b
479 self.assertEqual(gc.collect(), 4)
480 self.assertEqual(len(gc.garbage), garbagelen)
481
482 def test_boom2_new(self):
483 class Boom2_New(object):
484 def __init__(self):
485 self.x = 0
486
487 def __getattr__(self, someattribute):
488 self.x += 1
489 if self.x > 1:
490 del self.attr
491 raise AttributeError
492
493 a = Boom2_New()
494 b = Boom2_New()
495 a.attr = b
496 b.attr = a
497
498 gc.collect()
499 garbagelen = len(gc.garbage)
500 del a, b
501 self.assertEqual(gc.collect(), 4)
502 self.assertEqual(len(gc.garbage), garbagelen)
503
504 def test_get_referents(self):
505 alist = [1, 3, 5]
506 got = gc.get_referents(alist)
507 got.sort()
508 self.assertEqual(got, alist)
509
510 atuple = tuple(alist)
511 got = gc.get_referents(atuple)
512 got.sort()
513 self.assertEqual(got, alist)
514
515 adict = {1: 3, 5: 7}
516 expected = [1, 3, 5, 7]
517 got = gc.get_referents(adict)
518 got.sort()
519 self.assertEqual(got, expected)
520
521 got = gc.get_referents([1, 2], {3: 4}, (0, 0, 0))
522 got.sort()
Guido van Rossum805365e2007-05-07 22:24:25 +0000523 self.assertEqual(got, [0, 0] + list(range(5)))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000524
525 self.assertEqual(gc.get_referents(1, 'a', 4j), [])
526
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000527 def test_is_tracked(self):
528 # Atomic built-in types are not tracked, user-defined objects and
529 # mutable containers are.
530 # NOTE: types with special optimizations (e.g. tuple) have tests
531 # in their own test files instead.
532 self.assertFalse(gc.is_tracked(None))
533 self.assertFalse(gc.is_tracked(1))
534 self.assertFalse(gc.is_tracked(1.0))
535 self.assertFalse(gc.is_tracked(1.0 + 5.0j))
536 self.assertFalse(gc.is_tracked(True))
537 self.assertFalse(gc.is_tracked(False))
538 self.assertFalse(gc.is_tracked(b"a"))
539 self.assertFalse(gc.is_tracked("a"))
540 self.assertFalse(gc.is_tracked(bytearray(b"a")))
541 self.assertFalse(gc.is_tracked(type))
542 self.assertFalse(gc.is_tracked(int))
543 self.assertFalse(gc.is_tracked(object))
544 self.assertFalse(gc.is_tracked(object()))
545
546 class UserClass:
547 pass
Antoine Pitroua63cc212015-04-13 20:10:06 +0200548
549 class UserInt(int):
550 pass
551
552 # Base class is object; no extra fields.
553 class UserClassSlots:
554 __slots__ = ()
555
556 # Base class is fixed size larger than object; no extra fields.
557 class UserFloatSlots(float):
558 __slots__ = ()
559
560 # Base class is variable size; no extra fields.
561 class UserIntSlots(int):
562 __slots__ = ()
563
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000564 self.assertTrue(gc.is_tracked(gc))
565 self.assertTrue(gc.is_tracked(UserClass))
566 self.assertTrue(gc.is_tracked(UserClass()))
Antoine Pitroua63cc212015-04-13 20:10:06 +0200567 self.assertTrue(gc.is_tracked(UserInt()))
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000568 self.assertTrue(gc.is_tracked([]))
569 self.assertTrue(gc.is_tracked(set()))
Antoine Pitroua63cc212015-04-13 20:10:06 +0200570 self.assertFalse(gc.is_tracked(UserClassSlots()))
571 self.assertFalse(gc.is_tracked(UserFloatSlots()))
572 self.assertFalse(gc.is_tracked(UserIntSlots()))
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000573
Guido van Rossumd8faa362007-04-27 19:54:29 +0000574 def test_bug1055820b(self):
575 # Corresponds to temp2b.py in the bug report.
576
577 ouch = []
578 def callback(ignored):
579 ouch[:] = [wr() for wr in WRs]
580
581 Cs = [C1055820(i) for i in range(2)]
582 WRs = [weakref.ref(c, callback) for c in Cs]
583 c = None
584
585 gc.collect()
586 self.assertEqual(len(ouch), 0)
587 # Make the two instances trash, and collect again. The bug was that
588 # the callback materialized a strong reference to an instance, but gc
589 # cleared the instance's dict anyway.
590 Cs = None
591 gc.collect()
592 self.assertEqual(len(ouch), 2) # else the callbacks didn't run
593 for x in ouch:
594 # If the callback resurrected one of these guys, the instance
595 # would be damaged, with an empty __dict__.
596 self.assertEqual(x, None)
597
Tim Peters5fbc7b12014-05-08 17:42:19 -0500598 def test_bug21435(self):
599 # This is a poor test - its only virtue is that it happened to
600 # segfault on Tim's Windows box before the patch for 21435 was
601 # applied. That's a nasty bug relying on specific pieces of cyclic
602 # trash appearing in exactly the right order in finalize_garbage()'s
603 # input list.
604 # But there's no reliable way to force that order from Python code,
605 # so over time chances are good this test won't really be testing much
606 # of anything anymore. Still, if it blows up, there's _some_
607 # problem ;-)
608 gc.collect()
609
610 class A:
611 pass
612
613 class B:
614 def __init__(self, x):
615 self.x = x
616
617 def __del__(self):
618 self.attr = None
619
620 def do_work():
621 a = A()
622 b = B(A())
623
624 a.attr = b
625 b.attr = a
626
627 do_work()
628 gc.collect() # this blows up (bad C pointer) when it fails
629
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200630 @cpython_only
Antoine Pitrou696e0352010-08-08 22:18:46 +0000631 def test_garbage_at_shutdown(self):
632 import subprocess
633 code = """if 1:
634 import gc
Antoine Pitrou796564c2013-07-30 19:59:21 +0200635 import _testcapi
636 @_testcapi.with_tp_del
Antoine Pitrou696e0352010-08-08 22:18:46 +0000637 class X:
638 def __init__(self, name):
639 self.name = name
640 def __repr__(self):
641 return "<X %%r>" %% self.name
Antoine Pitrou796564c2013-07-30 19:59:21 +0200642 def __tp_del__(self):
Antoine Pitrou696e0352010-08-08 22:18:46 +0000643 pass
644
645 x = X('first')
646 x.x = x
647 x.y = X('second')
648 del x
Antoine Pitrou2ed94eb2010-09-14 09:48:39 +0000649 gc.set_debug(%s)
Antoine Pitrou696e0352010-08-08 22:18:46 +0000650 """
651 def run_command(code):
Georg Brandl08be72d2010-10-24 15:11:22 +0000652 p = subprocess.Popen([sys.executable, "-Wd", "-c", code],
Antoine Pitrou696e0352010-08-08 22:18:46 +0000653 stdout=subprocess.PIPE,
654 stderr=subprocess.PIPE)
655 stdout, stderr = p.communicate()
Brian Curtin8291af22010-11-01 16:40:17 +0000656 p.stdout.close()
657 p.stderr.close()
Antoine Pitrou696e0352010-08-08 22:18:46 +0000658 self.assertEqual(p.returncode, 0)
659 self.assertEqual(stdout.strip(), b"")
660 return strip_python_stderr(stderr)
661
Antoine Pitrou2ed94eb2010-09-14 09:48:39 +0000662 stderr = run_command(code % "0")
Georg Brandl08be72d2010-10-24 15:11:22 +0000663 self.assertIn(b"ResourceWarning: gc: 2 uncollectable objects at "
664 b"shutdown; use", stderr)
Antoine Pitrouaee47562010-09-16 15:04:49 +0000665 self.assertNotIn(b"<X 'first'>", stderr)
Antoine Pitrou696e0352010-08-08 22:18:46 +0000666 # With DEBUG_UNCOLLECTABLE, the garbage list gets printed
Antoine Pitrou2ed94eb2010-09-14 09:48:39 +0000667 stderr = run_command(code % "gc.DEBUG_UNCOLLECTABLE")
Georg Brandl08be72d2010-10-24 15:11:22 +0000668 self.assertIn(b"ResourceWarning: gc: 2 uncollectable objects at "
669 b"shutdown", stderr)
Antoine Pitrouaee47562010-09-16 15:04:49 +0000670 self.assertTrue(
671 (b"[<X 'first'>, <X 'second'>]" in stderr) or
672 (b"[<X 'second'>, <X 'first'>]" in stderr), stderr)
Antoine Pitrou2ed94eb2010-09-14 09:48:39 +0000673 # With DEBUG_SAVEALL, no additional message should get printed
674 # (because gc.garbage also contains normally reclaimable cyclic
675 # references, and its elements get printed at runtime anyway).
676 stderr = run_command(code % "gc.DEBUG_SAVEALL")
677 self.assertNotIn(b"uncollectable objects at shutdown", stderr)
678
Serhiy Storchakaa7930372016-07-03 22:27:26 +0300679 @requires_type_collecting
Antoine Pitrou5f454a02013-05-06 21:15:57 +0200680 def test_gc_main_module_at_shutdown(self):
681 # Create a reference cycle through the __main__ module and check
682 # it gets collected at interpreter shutdown.
683 code = """if 1:
Antoine Pitrou5f454a02013-05-06 21:15:57 +0200684 class C:
685 def __del__(self):
686 print('__del__ called')
687 l = [C()]
688 l.append(l)
689 """
690 rc, out, err = assert_python_ok('-c', code)
691 self.assertEqual(out.strip(), b'__del__ called')
692
Serhiy Storchakaa7930372016-07-03 22:27:26 +0300693 @requires_type_collecting
Antoine Pitrou5f454a02013-05-06 21:15:57 +0200694 def test_gc_ordinary_module_at_shutdown(self):
695 # Same as above, but with a non-__main__ module.
696 with temp_dir() as script_dir:
697 module = """if 1:
Antoine Pitrou5f454a02013-05-06 21:15:57 +0200698 class C:
699 def __del__(self):
700 print('__del__ called')
701 l = [C()]
702 l.append(l)
703 """
704 code = """if 1:
705 import sys
706 sys.path.insert(0, %r)
707 import gctest
708 """ % (script_dir,)
709 make_script(script_dir, 'gctest', module)
710 rc, out, err = assert_python_ok('-c', code)
711 self.assertEqual(out.strip(), b'__del__ called')
712
Antoine Pitroud4156c12012-10-30 22:43:19 +0100713 def test_get_stats(self):
714 stats = gc.get_stats()
715 self.assertEqual(len(stats), 3)
716 for st in stats:
717 self.assertIsInstance(st, dict)
718 self.assertEqual(set(st),
719 {"collected", "collections", "uncollectable"})
720 self.assertGreaterEqual(st["collected"], 0)
721 self.assertGreaterEqual(st["collections"], 0)
722 self.assertGreaterEqual(st["uncollectable"], 0)
723 # Check that collection counts are incremented correctly
724 if gc.isenabled():
725 self.addCleanup(gc.enable)
726 gc.disable()
727 old = gc.get_stats()
728 gc.collect(0)
729 new = gc.get_stats()
730 self.assertEqual(new[0]["collections"], old[0]["collections"] + 1)
731 self.assertEqual(new[1]["collections"], old[1]["collections"])
732 self.assertEqual(new[2]["collections"], old[2]["collections"])
733 gc.collect(2)
734 new = gc.get_stats()
735 self.assertEqual(new[0]["collections"], old[0]["collections"] + 1)
736 self.assertEqual(new[1]["collections"], old[1]["collections"])
737 self.assertEqual(new[2]["collections"], old[2]["collections"] + 1)
738
brainfvckc75edab2017-10-16 12:49:41 -0700739 def test_freeze(self):
740 gc.freeze()
741 self.assertGreater(gc.get_freeze_count(), 0)
742 gc.unfreeze()
743 self.assertEqual(gc.get_freeze_count(), 0)
744
Antoine Pitrou696e0352010-08-08 22:18:46 +0000745
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +0000746class GCCallbackTests(unittest.TestCase):
747 def setUp(self):
748 # Save gc state and disable it.
749 self.enabled = gc.isenabled()
750 gc.disable()
751 self.debug = gc.get_debug()
752 gc.set_debug(0)
753 gc.callbacks.append(self.cb1)
754 gc.callbacks.append(self.cb2)
Antoine Pitrou6b64fc62012-04-16 21:29:02 +0200755 self.othergarbage = []
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +0000756
757 def tearDown(self):
758 # Restore gc state
759 del self.visit
760 gc.callbacks.remove(self.cb1)
761 gc.callbacks.remove(self.cb2)
762 gc.set_debug(self.debug)
763 if self.enabled:
764 gc.enable()
765 # destroy any uncollectables
766 gc.collect()
767 for obj in gc.garbage:
768 if isinstance(obj, Uncollectable):
769 obj.partner = None
770 del gc.garbage[:]
Antoine Pitrou6b64fc62012-04-16 21:29:02 +0200771 del self.othergarbage
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +0000772 gc.collect()
773
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +0000774 def preclean(self):
775 # Remove all fluff from the system. Invoke this function
776 # manually rather than through self.setUp() for maximum
777 # safety.
778 self.visit = []
779 gc.collect()
780 garbage, gc.garbage[:] = gc.garbage[:], []
781 self.othergarbage.append(garbage)
782 self.visit = []
783
784 def cb1(self, phase, info):
785 self.visit.append((1, phase, dict(info)))
786
787 def cb2(self, phase, info):
788 self.visit.append((2, phase, dict(info)))
789 if phase == "stop" and hasattr(self, "cleanup"):
790 # Clean Uncollectable from garbage
791 uc = [e for e in gc.garbage if isinstance(e, Uncollectable)]
792 gc.garbage[:] = [e for e in gc.garbage
793 if not isinstance(e, Uncollectable)]
794 for e in uc:
795 e.partner = None
796
Antoine Pitroude3c73b2012-04-16 21:29:58 +0200797 def test_collect(self):
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +0000798 self.preclean()
799 gc.collect()
800 # Algorithmically verify the contents of self.visit
801 # because it is long and tortuous.
802
803 # Count the number of visits to each callback
804 n = [v[0] for v in self.visit]
805 n1 = [i for i in n if i == 1]
806 n2 = [i for i in n if i == 2]
807 self.assertEqual(n1, [1]*2)
808 self.assertEqual(n2, [2]*2)
809
810 # Count that we got the right number of start and stop callbacks.
811 n = [v[1] for v in self.visit]
812 n1 = [i for i in n if i == "start"]
813 n2 = [i for i in n if i == "stop"]
814 self.assertEqual(n1, ["start"]*2)
815 self.assertEqual(n2, ["stop"]*2)
816
817 # Check that we got the right info dict for all callbacks
818 for v in self.visit:
819 info = v[2]
820 self.assertTrue("generation" in info)
821 self.assertTrue("collected" in info)
822 self.assertTrue("uncollectable" in info)
823
Antoine Pitroude3c73b2012-04-16 21:29:58 +0200824 def test_collect_generation(self):
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +0000825 self.preclean()
826 gc.collect(2)
827 for v in self.visit:
828 info = v[2]
829 self.assertEqual(info["generation"], 2)
830
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200831 @cpython_only
Antoine Pitroude3c73b2012-04-16 21:29:58 +0200832 def test_collect_garbage(self):
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +0000833 self.preclean()
834 # Each of these cause four objects to be garbage: Two
835 # Uncolectables and their instance dicts.
836 Uncollectable()
837 Uncollectable()
838 C1055820(666)
839 gc.collect()
840 for v in self.visit:
841 if v[1] != "stop":
842 continue
843 info = v[2]
844 self.assertEqual(info["collected"], 2)
845 self.assertEqual(info["uncollectable"], 8)
846
847 # We should now have the Uncollectables in gc.garbage
848 self.assertEqual(len(gc.garbage), 4)
849 for e in gc.garbage:
850 self.assertIsInstance(e, Uncollectable)
851
852 # Now, let our callback handle the Uncollectable instances
853 self.cleanup=True
854 self.visit = []
855 gc.garbage[:] = []
856 gc.collect()
857 for v in self.visit:
858 if v[1] != "stop":
859 continue
860 info = v[2]
861 self.assertEqual(info["collected"], 0)
862 self.assertEqual(info["uncollectable"], 4)
863
864 # Uncollectables should be gone
865 self.assertEqual(len(gc.garbage), 0)
866
867
Guido van Rossumd8faa362007-04-27 19:54:29 +0000868class GCTogglingTests(unittest.TestCase):
869 def setUp(self):
870 gc.enable()
871
872 def tearDown(self):
873 gc.disable()
874
875 def test_bug1055820c(self):
876 # Corresponds to temp2c.py in the bug report. This is pretty
877 # elaborate.
878
879 c0 = C1055820(0)
880 # Move c0 into generation 2.
881 gc.collect()
882
883 c1 = C1055820(1)
884 c1.keep_c0_alive = c0
885 del c0.loop # now only c1 keeps c0 alive
886
887 c2 = C1055820(2)
888 c2wr = weakref.ref(c2) # no callback!
889
890 ouch = []
891 def callback(ignored):
Tim Petersead8b7a2004-10-30 23:09:22 +0000892 ouch[:] = [c2wr()]
893
Guido van Rossumd8faa362007-04-27 19:54:29 +0000894 # The callback gets associated with a wr on an object in generation 2.
895 c0wr = weakref.ref(c0, callback)
Tim Petersead8b7a2004-10-30 23:09:22 +0000896
Guido van Rossumd8faa362007-04-27 19:54:29 +0000897 c0 = c1 = c2 = None
Tim Petersead8b7a2004-10-30 23:09:22 +0000898
Guido van Rossumd8faa362007-04-27 19:54:29 +0000899 # What we've set up: c0, c1, and c2 are all trash now. c0 is in
900 # generation 2. The only thing keeping it alive is that c1 points to
901 # it. c1 and c2 are in generation 0, and are in self-loops. There's a
902 # global weakref to c2 (c2wr), but that weakref has no callback.
903 # There's also a global weakref to c0 (c0wr), and that does have a
904 # callback, and that callback references c2 via c2wr().
905 #
906 # c0 has a wr with callback, which references c2wr
907 # ^
908 # |
909 # | Generation 2 above dots
910 #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . .
911 # | Generation 0 below dots
912 # |
913 # |
914 # ^->c1 ^->c2 has a wr but no callback
915 # | | | |
916 # <--v <--v
917 #
918 # So this is the nightmare: when generation 0 gets collected, we see
919 # that c2 has a callback-free weakref, and c1 doesn't even have a
920 # weakref. Collecting generation 0 doesn't see c0 at all, and c0 is
921 # the only object that has a weakref with a callback. gc clears c1
922 # and c2. Clearing c1 has the side effect of dropping the refcount on
923 # c0 to 0, so c0 goes away (despite that it's in an older generation)
924 # and c0's wr callback triggers. That in turn materializes a reference
925 # to c2 via c2wr(), but c2 gets cleared anyway by gc.
Tim Petersead8b7a2004-10-30 23:09:22 +0000926
Guido van Rossumd8faa362007-04-27 19:54:29 +0000927 # We want to let gc happen "naturally", to preserve the distinction
928 # between generations.
929 junk = []
930 i = 0
931 detector = GC_Detector()
932 while not detector.gc_happened:
933 i += 1
934 if i > 10000:
935 self.fail("gc didn't happen after 10000 iterations")
936 self.assertEqual(len(ouch), 0)
937 junk.append([]) # this will eventually trigger gc
Tim Petersead8b7a2004-10-30 23:09:22 +0000938
Guido van Rossumd8faa362007-04-27 19:54:29 +0000939 self.assertEqual(len(ouch), 1) # else the callback wasn't invoked
940 for x in ouch:
941 # If the callback resurrected c2, the instance would be damaged,
942 # with an empty __dict__.
943 self.assertEqual(x, None)
Tim Petersead8b7a2004-10-30 23:09:22 +0000944
Guido van Rossumd8faa362007-04-27 19:54:29 +0000945 def test_bug1055820d(self):
946 # Corresponds to temp2d.py in the bug report. This is very much like
947 # test_bug1055820c, but uses a __del__ method instead of a weakref
948 # callback to sneak in a resurrection of cyclic trash.
Tim Petersead8b7a2004-10-30 23:09:22 +0000949
Guido van Rossumd8faa362007-04-27 19:54:29 +0000950 ouch = []
951 class D(C1055820):
952 def __del__(self):
953 ouch[:] = [c2wr()]
Tim Petersead8b7a2004-10-30 23:09:22 +0000954
Guido van Rossumd8faa362007-04-27 19:54:29 +0000955 d0 = D(0)
956 # Move all the above into generation 2.
957 gc.collect()
Tim Petersead8b7a2004-10-30 23:09:22 +0000958
Guido van Rossumd8faa362007-04-27 19:54:29 +0000959 c1 = C1055820(1)
960 c1.keep_d0_alive = d0
961 del d0.loop # now only c1 keeps d0 alive
Tim Petersead8b7a2004-10-30 23:09:22 +0000962
Guido van Rossumd8faa362007-04-27 19:54:29 +0000963 c2 = C1055820(2)
964 c2wr = weakref.ref(c2) # no callback!
Tim Petersead8b7a2004-10-30 23:09:22 +0000965
Guido van Rossumd8faa362007-04-27 19:54:29 +0000966 d0 = c1 = c2 = None
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000967
Guido van Rossumd8faa362007-04-27 19:54:29 +0000968 # What we've set up: d0, c1, and c2 are all trash now. d0 is in
969 # generation 2. The only thing keeping it alive is that c1 points to
970 # it. c1 and c2 are in generation 0, and are in self-loops. There's
971 # a global weakref to c2 (c2wr), but that weakref has no callback.
972 # There are no other weakrefs.
973 #
974 # d0 has a __del__ method that references c2wr
975 # ^
976 # |
977 # | Generation 2 above dots
978 #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . .
979 # | Generation 0 below dots
980 # |
981 # |
982 # ^->c1 ^->c2 has a wr but no callback
983 # | | | |
984 # <--v <--v
985 #
986 # So this is the nightmare: when generation 0 gets collected, we see
987 # that c2 has a callback-free weakref, and c1 doesn't even have a
988 # weakref. Collecting generation 0 doesn't see d0 at all. gc clears
989 # c1 and c2. Clearing c1 has the side effect of dropping the refcount
990 # on d0 to 0, so d0 goes away (despite that it's in an older
991 # generation) and d0's __del__ triggers. That in turn materializes
992 # a reference to c2 via c2wr(), but c2 gets cleared anyway by gc.
993
994 # We want to let gc happen "naturally", to preserve the distinction
995 # between generations.
996 detector = GC_Detector()
997 junk = []
998 i = 0
999 while not detector.gc_happened:
1000 i += 1
1001 if i > 10000:
1002 self.fail("gc didn't happen after 10000 iterations")
1003 self.assertEqual(len(ouch), 0)
1004 junk.append([]) # this will eventually trigger gc
1005
1006 self.assertEqual(len(ouch), 1) # else __del__ wasn't invoked
1007 for x in ouch:
1008 # If __del__ resurrected c2, the instance would be damaged, with an
1009 # empty __dict__.
1010 self.assertEqual(x, None)
1011
Pablo Galindo72a0d212018-01-29 20:37:09 +00001012 def test_ensure_disabled(self):
1013 original_status = gc.isenabled()
1014
1015 with gc.ensure_disabled():
1016 inside_status = gc.isenabled()
1017
1018 after_status = gc.isenabled()
1019 self.assertEqual(original_status, True)
1020 self.assertEqual(inside_status, False)
1021 self.assertEqual(after_status, True)
1022
1023 def test_ensure_disabled_with_gc_disabled(self):
1024 gc.disable()
1025
1026 original_status = gc.isenabled()
1027
1028 with gc.ensure_disabled():
1029 inside_status = gc.isenabled()
1030
1031 after_status = gc.isenabled()
1032 self.assertEqual(original_status, False)
1033 self.assertEqual(inside_status, False)
1034 self.assertEqual(after_status, False)
1035
1036 @reap_threads
1037 def test_ensure_disabled_thread(self):
1038
1039 thread_original_status = None
1040 thread_inside_status = None
1041 thread_after_status = None
1042
1043 def disabling_thread():
1044 nonlocal thread_original_status
1045 nonlocal thread_inside_status
1046 nonlocal thread_after_status
1047 thread_original_status = gc.isenabled()
1048
1049 with gc.ensure_disabled():
1050 time.sleep(0.01)
1051 thread_inside_status = gc.isenabled()
1052
1053 thread_after_status = gc.isenabled()
1054
1055 original_status = gc.isenabled()
1056
1057 with warnings.catch_warnings(record=True) as w, gc.ensure_disabled():
1058 inside_status_before_thread = gc.isenabled()
1059 thread = threading.Thread(target=disabling_thread)
1060 thread.start()
1061 inside_status_after_thread = gc.isenabled()
1062
1063 after_status = gc.isenabled()
1064 thread.join()
1065
1066 self.assertEqual(len(w), 1)
1067 self.assertTrue(issubclass(w[-1].category, RuntimeWarning))
1068 self.assertEqual("Garbage collector enabled while another thread is "
1069 "inside gc.ensure_enabled", str(w[-1].message))
1070 self.assertEqual(original_status, True)
1071 self.assertEqual(inside_status_before_thread, False)
1072 self.assertEqual(thread_original_status, False)
1073 self.assertEqual(thread_inside_status, True)
1074 self.assertEqual(thread_after_status, False)
1075 self.assertEqual(inside_status_after_thread, False)
1076 self.assertEqual(after_status, True)
1077
1078
Guido van Rossumd8faa362007-04-27 19:54:29 +00001079def test_main():
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +00001080 enabled = gc.isenabled()
1081 gc.disable()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001082 assert not gc.isenabled()
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001083 debug = gc.get_debug()
1084 gc.set_debug(debug & ~gc.DEBUG_LEAK) # this test is supposed to leak
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +00001085
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001086 try:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001087 gc.collect() # Delete 2nd generation garbage
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +00001088 run_unittest(GCTests, GCTogglingTests, GCCallbackTests)
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001089 finally:
1090 gc.set_debug(debug)
1091 # test gc.enable() even if GC is disabled by default
1092 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001093 print("restoring automatic collection")
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001094 # make sure to always test gc.enable()
1095 gc.enable()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001096 assert gc.isenabled()
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001097 if not enabled:
1098 gc.disable()
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +00001099
Guido van Rossumd8faa362007-04-27 19:54:29 +00001100if __name__ == "__main__":
1101 test_main()