test_gc.py 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483
  1. import unittest
  2. import unittest.mock
  3. from test.support import (verbose, refcount_test,
  4. cpython_only, requires_subprocess)
  5. from test.support.import_helper import import_module
  6. from test.support.os_helper import temp_dir, TESTFN, unlink
  7. from test.support.script_helper import assert_python_ok, make_script
  8. from test.support import threading_helper
  9. import gc
  10. import sys
  11. import sysconfig
  12. import textwrap
  13. import threading
  14. import time
  15. import weakref
  16. try:
  17. from _testcapi import with_tp_del
  18. except ImportError:
  19. def with_tp_del(cls):
  20. class C(object):
  21. def __new__(cls, *args, **kwargs):
  22. raise TypeError('requires _testcapi.with_tp_del')
  23. return C
  24. try:
  25. from _testcapi import ContainerNoGC
  26. except ImportError:
  27. ContainerNoGC = None
  28. ### Support code
  29. ###############################################################################
  30. # Bug 1055820 has several tests of longstanding bugs involving weakrefs and
  31. # cyclic gc.
  32. # An instance of C1055820 has a self-loop, so becomes cyclic trash when
  33. # unreachable.
  34. class C1055820(object):
  35. def __init__(self, i):
  36. self.i = i
  37. self.loop = self
  38. class GC_Detector(object):
  39. # Create an instance I. Then gc hasn't happened again so long as
  40. # I.gc_happened is false.
  41. def __init__(self):
  42. self.gc_happened = False
  43. def it_happened(ignored):
  44. self.gc_happened = True
  45. # Create a piece of cyclic trash that triggers it_happened when
  46. # gc collects it.
  47. self.wr = weakref.ref(C1055820(666), it_happened)
  48. @with_tp_del
  49. class Uncollectable(object):
  50. """Create a reference cycle with multiple __del__ methods.
  51. An object in a reference cycle will never have zero references,
  52. and so must be garbage collected. If one or more objects in the
  53. cycle have __del__ methods, the gc refuses to guess an order,
  54. and leaves the cycle uncollected."""
  55. def __init__(self, partner=None):
  56. if partner is None:
  57. self.partner = Uncollectable(partner=self)
  58. else:
  59. self.partner = partner
  60. def __tp_del__(self):
  61. pass
  62. if sysconfig.get_config_vars().get('PY_CFLAGS', ''):
  63. BUILD_WITH_NDEBUG = ('-DNDEBUG' in sysconfig.get_config_vars()['PY_CFLAGS'])
  64. else:
  65. # Usually, sys.gettotalrefcount() is only present if Python has been
  66. # compiled in debug mode. If it's missing, expect that Python has
  67. # been released in release mode: with NDEBUG defined.
  68. BUILD_WITH_NDEBUG = (not hasattr(sys, 'gettotalrefcount'))
  69. ### Tests
  70. ###############################################################################
  71. class GCTests(unittest.TestCase):
  72. def test_list(self):
  73. l = []
  74. l.append(l)
  75. gc.collect()
  76. del l
  77. self.assertEqual(gc.collect(), 1)
  78. def test_dict(self):
  79. d = {}
  80. d[1] = d
  81. gc.collect()
  82. del d
  83. self.assertEqual(gc.collect(), 1)
  84. def test_tuple(self):
  85. # since tuples are immutable we close the loop with a list
  86. l = []
  87. t = (l,)
  88. l.append(t)
  89. gc.collect()
  90. del t
  91. del l
  92. self.assertEqual(gc.collect(), 2)
  93. def test_class(self):
  94. class A:
  95. pass
  96. A.a = A
  97. gc.collect()
  98. del A
  99. self.assertNotEqual(gc.collect(), 0)
  100. def test_newstyleclass(self):
  101. class A(object):
  102. pass
  103. gc.collect()
  104. del A
  105. self.assertNotEqual(gc.collect(), 0)
  106. def test_instance(self):
  107. class A:
  108. pass
  109. a = A()
  110. a.a = a
  111. gc.collect()
  112. del a
  113. self.assertNotEqual(gc.collect(), 0)
  114. def test_newinstance(self):
  115. class A(object):
  116. pass
  117. a = A()
  118. a.a = a
  119. gc.collect()
  120. del a
  121. self.assertNotEqual(gc.collect(), 0)
  122. class B(list):
  123. pass
  124. class C(B, A):
  125. pass
  126. a = C()
  127. a.a = a
  128. gc.collect()
  129. del a
  130. self.assertNotEqual(gc.collect(), 0)
  131. del B, C
  132. self.assertNotEqual(gc.collect(), 0)
  133. A.a = A()
  134. del A
  135. self.assertNotEqual(gc.collect(), 0)
  136. self.assertEqual(gc.collect(), 0)
  137. def test_method(self):
  138. # Tricky: self.__init__ is a bound method, it references the instance.
  139. class A:
  140. def __init__(self):
  141. self.init = self.__init__
  142. a = A()
  143. gc.collect()
  144. del a
  145. self.assertNotEqual(gc.collect(), 0)
  146. @cpython_only
  147. def test_legacy_finalizer(self):
  148. # A() is uncollectable if it is part of a cycle, make sure it shows up
  149. # in gc.garbage.
  150. @with_tp_del
  151. class A:
  152. def __tp_del__(self): pass
  153. class B:
  154. pass
  155. a = A()
  156. a.a = a
  157. id_a = id(a)
  158. b = B()
  159. b.b = b
  160. gc.collect()
  161. del a
  162. del b
  163. self.assertNotEqual(gc.collect(), 0)
  164. for obj in gc.garbage:
  165. if id(obj) == id_a:
  166. del obj.a
  167. break
  168. else:
  169. self.fail("didn't find obj in garbage (finalizer)")
  170. gc.garbage.remove(obj)
  171. @cpython_only
  172. def test_legacy_finalizer_newclass(self):
  173. # A() is uncollectable if it is part of a cycle, make sure it shows up
  174. # in gc.garbage.
  175. @with_tp_del
  176. class A(object):
  177. def __tp_del__(self): pass
  178. class B(object):
  179. pass
  180. a = A()
  181. a.a = a
  182. id_a = id(a)
  183. b = B()
  184. b.b = b
  185. gc.collect()
  186. del a
  187. del b
  188. self.assertNotEqual(gc.collect(), 0)
  189. for obj in gc.garbage:
  190. if id(obj) == id_a:
  191. del obj.a
  192. break
  193. else:
  194. self.fail("didn't find obj in garbage (finalizer)")
  195. gc.garbage.remove(obj)
  196. def test_function(self):
  197. # Tricky: f -> d -> f, code should call d.clear() after the exec to
  198. # break the cycle.
  199. d = {}
  200. exec("def f(): pass\n", d)
  201. gc.collect()
  202. del d
  203. self.assertEqual(gc.collect(), 2)
  204. def test_function_tp_clear_leaves_consistent_state(self):
  205. # https://github.com/python/cpython/issues/91636
  206. code = """if 1:
  207. import gc
  208. import weakref
  209. class LateFin:
  210. __slots__ = ('ref',)
  211. def __del__(self):
  212. # 8. Now `latefin`'s finalizer is called. Here we
  213. # obtain a reference to `func`, which is currently
  214. # undergoing `tp_clear`.
  215. global func
  216. func = self.ref()
  217. class Cyclic(tuple):
  218. __slots__ = ()
  219. # 4. The finalizers of all garbage objects are called. In
  220. # this case this is only us as `func` doesn't have a
  221. # finalizer.
  222. def __del__(self):
  223. # 5. Create a weakref to `func` now. If we had created
  224. # it earlier, it would have been cleared by the
  225. # garbage collector before calling the finalizers.
  226. self[1].ref = weakref.ref(self[0])
  227. # 6. Drop the global reference to `latefin`. The only
  228. # remaining reference is the one we have.
  229. global latefin
  230. del latefin
  231. # 7. Now `func` is `tp_clear`-ed. This drops the last
  232. # reference to `Cyclic`, which gets `tp_dealloc`-ed.
  233. # This drops the last reference to `latefin`.
  234. latefin = LateFin()
  235. def func():
  236. pass
  237. cyc = tuple.__new__(Cyclic, (func, latefin))
  238. # 1. Create a reference cycle of `cyc` and `func`.
  239. func.__module__ = cyc
  240. # 2. Make the cycle unreachable, but keep the global reference
  241. # to `latefin` so that it isn't detected as garbage. This
  242. # way its finalizer will not be called immediately.
  243. del func, cyc
  244. # 3. Invoke garbage collection,
  245. # which will find `cyc` and `func` as garbage.
  246. gc.collect()
  247. # 9. Previously, this would crash because `func_qualname`
  248. # had been NULL-ed out by func_clear().
  249. print(f"{func=}")
  250. """
  251. # We're mostly just checking that this doesn't crash.
  252. rc, stdout, stderr = assert_python_ok("-c", code)
  253. self.assertEqual(rc, 0)
  254. self.assertRegex(stdout, rb"""\A\s*func=<function at \S+>\s*\Z""")
  255. self.assertFalse(stderr)
  256. @refcount_test
  257. def test_frame(self):
  258. def f():
  259. frame = sys._getframe()
  260. gc.collect()
  261. f()
  262. self.assertEqual(gc.collect(), 1)
  263. def test_saveall(self):
  264. # Verify that cyclic garbage like lists show up in gc.garbage if the
  265. # SAVEALL option is enabled.
  266. # First make sure we don't save away other stuff that just happens to
  267. # be waiting for collection.
  268. gc.collect()
  269. # if this fails, someone else created immortal trash
  270. self.assertEqual(gc.garbage, [])
  271. L = []
  272. L.append(L)
  273. id_L = id(L)
  274. debug = gc.get_debug()
  275. gc.set_debug(debug | gc.DEBUG_SAVEALL)
  276. del L
  277. gc.collect()
  278. gc.set_debug(debug)
  279. self.assertEqual(len(gc.garbage), 1)
  280. obj = gc.garbage.pop()
  281. self.assertEqual(id(obj), id_L)
  282. def test_del(self):
  283. # __del__ methods can trigger collection, make this to happen
  284. thresholds = gc.get_threshold()
  285. gc.enable()
  286. gc.set_threshold(1)
  287. class A:
  288. def __del__(self):
  289. dir(self)
  290. a = A()
  291. del a
  292. gc.disable()
  293. gc.set_threshold(*thresholds)
  294. def test_del_newclass(self):
  295. # __del__ methods can trigger collection, make this to happen
  296. thresholds = gc.get_threshold()
  297. gc.enable()
  298. gc.set_threshold(1)
  299. class A(object):
  300. def __del__(self):
  301. dir(self)
  302. a = A()
  303. del a
  304. gc.disable()
  305. gc.set_threshold(*thresholds)
  306. # The following two tests are fragile:
  307. # They precisely count the number of allocations,
  308. # which is highly implementation-dependent.
  309. # For example, disposed tuples are not freed, but reused.
  310. # To minimize variations, though, we first store the get_count() results
  311. # and check them at the end.
  312. @refcount_test
  313. def test_get_count(self):
  314. gc.collect()
  315. a, b, c = gc.get_count()
  316. x = []
  317. d, e, f = gc.get_count()
  318. self.assertEqual((b, c), (0, 0))
  319. self.assertEqual((e, f), (0, 0))
  320. # This is less fragile than asserting that a equals 0.
  321. self.assertLess(a, 5)
  322. # Between the two calls to get_count(), at least one object was
  323. # created (the list).
  324. self.assertGreater(d, a)
  325. @refcount_test
  326. def test_collect_generations(self):
  327. gc.collect()
  328. # This object will "trickle" into generation N + 1 after
  329. # each call to collect(N)
  330. x = []
  331. gc.collect(0)
  332. # x is now in gen 1
  333. a, b, c = gc.get_count()
  334. gc.collect(1)
  335. # x is now in gen 2
  336. d, e, f = gc.get_count()
  337. gc.collect(2)
  338. # x is now in gen 3
  339. g, h, i = gc.get_count()
  340. # We don't check a, d, g since their exact values depends on
  341. # internal implementation details of the interpreter.
  342. self.assertEqual((b, c), (1, 0))
  343. self.assertEqual((e, f), (0, 1))
  344. self.assertEqual((h, i), (0, 0))
  345. def test_trashcan(self):
  346. class Ouch:
  347. n = 0
  348. def __del__(self):
  349. Ouch.n = Ouch.n + 1
  350. if Ouch.n % 17 == 0:
  351. gc.collect()
  352. # "trashcan" is a hack to prevent stack overflow when deallocating
  353. # very deeply nested tuples etc. It works in part by abusing the
  354. # type pointer and refcount fields, and that can yield horrible
  355. # problems when gc tries to traverse the structures.
  356. # If this test fails (as it does in 2.0, 2.1 and 2.2), it will
  357. # most likely die via segfault.
  358. # Note: In 2.3 the possibility for compiling without cyclic gc was
  359. # removed, and that in turn allows the trashcan mechanism to work
  360. # via much simpler means (e.g., it never abuses the type pointer or
  361. # refcount fields anymore). Since it's much less likely to cause a
  362. # problem now, the various constants in this expensive (we force a lot
  363. # of full collections) test are cut back from the 2.2 version.
  364. gc.enable()
  365. N = 150
  366. for count in range(2):
  367. t = []
  368. for i in range(N):
  369. t = [t, Ouch()]
  370. u = []
  371. for i in range(N):
  372. u = [u, Ouch()]
  373. v = {}
  374. for i in range(N):
  375. v = {1: v, 2: Ouch()}
  376. gc.disable()
  377. @threading_helper.requires_working_threading()
  378. def test_trashcan_threads(self):
  379. # Issue #13992: trashcan mechanism should be thread-safe
  380. NESTING = 60
  381. N_THREADS = 2
  382. def sleeper_gen():
  383. """A generator that releases the GIL when closed or dealloc'ed."""
  384. try:
  385. yield
  386. finally:
  387. time.sleep(0.000001)
  388. class C(list):
  389. # Appending to a list is atomic, which avoids the use of a lock.
  390. inits = []
  391. dels = []
  392. def __init__(self, alist):
  393. self[:] = alist
  394. C.inits.append(None)
  395. def __del__(self):
  396. # This __del__ is called by subtype_dealloc().
  397. C.dels.append(None)
  398. # `g` will release the GIL when garbage-collected. This
  399. # helps assert subtype_dealloc's behaviour when threads
  400. # switch in the middle of it.
  401. g = sleeper_gen()
  402. next(g)
  403. # Now that __del__ is finished, subtype_dealloc will proceed
  404. # to call list_dealloc, which also uses the trashcan mechanism.
  405. def make_nested():
  406. """Create a sufficiently nested container object so that the
  407. trashcan mechanism is invoked when deallocating it."""
  408. x = C([])
  409. for i in range(NESTING):
  410. x = [C([x])]
  411. del x
  412. def run_thread():
  413. """Exercise make_nested() in a loop."""
  414. while not exit:
  415. make_nested()
  416. old_switchinterval = sys.getswitchinterval()
  417. sys.setswitchinterval(1e-5)
  418. try:
  419. exit = []
  420. threads = []
  421. for i in range(N_THREADS):
  422. t = threading.Thread(target=run_thread)
  423. threads.append(t)
  424. with threading_helper.start_threads(threads, lambda: exit.append(1)):
  425. time.sleep(1.0)
  426. finally:
  427. sys.setswitchinterval(old_switchinterval)
  428. gc.collect()
  429. self.assertEqual(len(C.inits), len(C.dels))
  430. def test_boom(self):
  431. class Boom:
  432. def __getattr__(self, someattribute):
  433. del self.attr
  434. raise AttributeError
  435. a = Boom()
  436. b = Boom()
  437. a.attr = b
  438. b.attr = a
  439. gc.collect()
  440. garbagelen = len(gc.garbage)
  441. del a, b
  442. # a<->b are in a trash cycle now. Collection will invoke
  443. # Boom.__getattr__ (to see whether a and b have __del__ methods), and
  444. # __getattr__ deletes the internal "attr" attributes as a side effect.
  445. # That causes the trash cycle to get reclaimed via refcounts falling to
  446. # 0, thus mutating the trash graph as a side effect of merely asking
  447. # whether __del__ exists. This used to (before 2.3b1) crash Python.
  448. # Now __getattr__ isn't called.
  449. self.assertEqual(gc.collect(), 2)
  450. self.assertEqual(len(gc.garbage), garbagelen)
  451. def test_boom2(self):
  452. class Boom2:
  453. def __init__(self):
  454. self.x = 0
  455. def __getattr__(self, someattribute):
  456. self.x += 1
  457. if self.x > 1:
  458. del self.attr
  459. raise AttributeError
  460. a = Boom2()
  461. b = Boom2()
  462. a.attr = b
  463. b.attr = a
  464. gc.collect()
  465. garbagelen = len(gc.garbage)
  466. del a, b
  467. # Much like test_boom(), except that __getattr__ doesn't break the
  468. # cycle until the second time gc checks for __del__. As of 2.3b1,
  469. # there isn't a second time, so this simply cleans up the trash cycle.
  470. # We expect a, b, a.__dict__ and b.__dict__ (4 objects) to get
  471. # reclaimed this way.
  472. self.assertEqual(gc.collect(), 2)
  473. self.assertEqual(len(gc.garbage), garbagelen)
  474. def test_boom_new(self):
  475. # boom__new and boom2_new are exactly like boom and boom2, except use
  476. # new-style classes.
  477. class Boom_New(object):
  478. def __getattr__(self, someattribute):
  479. del self.attr
  480. raise AttributeError
  481. a = Boom_New()
  482. b = Boom_New()
  483. a.attr = b
  484. b.attr = a
  485. gc.collect()
  486. garbagelen = len(gc.garbage)
  487. del a, b
  488. self.assertEqual(gc.collect(), 2)
  489. self.assertEqual(len(gc.garbage), garbagelen)
  490. def test_boom2_new(self):
  491. class Boom2_New(object):
  492. def __init__(self):
  493. self.x = 0
  494. def __getattr__(self, someattribute):
  495. self.x += 1
  496. if self.x > 1:
  497. del self.attr
  498. raise AttributeError
  499. a = Boom2_New()
  500. b = Boom2_New()
  501. a.attr = b
  502. b.attr = a
  503. gc.collect()
  504. garbagelen = len(gc.garbage)
  505. del a, b
  506. self.assertEqual(gc.collect(), 2)
  507. self.assertEqual(len(gc.garbage), garbagelen)
  508. def test_get_referents(self):
  509. alist = [1, 3, 5]
  510. got = gc.get_referents(alist)
  511. got.sort()
  512. self.assertEqual(got, alist)
  513. atuple = tuple(alist)
  514. got = gc.get_referents(atuple)
  515. got.sort()
  516. self.assertEqual(got, alist)
  517. adict = {1: 3, 5: 7}
  518. expected = [1, 3, 5, 7]
  519. got = gc.get_referents(adict)
  520. got.sort()
  521. self.assertEqual(got, expected)
  522. got = gc.get_referents([1, 2], {3: 4}, (0, 0, 0))
  523. got.sort()
  524. self.assertEqual(got, [0, 0] + list(range(5)))
  525. self.assertEqual(gc.get_referents(1, 'a', 4j), [])
  526. def test_is_tracked(self):
  527. # Atomic built-in types are not tracked, user-defined objects and
  528. # mutable containers are.
  529. # NOTE: types with special optimizations (e.g. tuple) have tests
  530. # in their own test files instead.
  531. self.assertFalse(gc.is_tracked(None))
  532. self.assertFalse(gc.is_tracked(1))
  533. self.assertFalse(gc.is_tracked(1.0))
  534. self.assertFalse(gc.is_tracked(1.0 + 5.0j))
  535. self.assertFalse(gc.is_tracked(True))
  536. self.assertFalse(gc.is_tracked(False))
  537. self.assertFalse(gc.is_tracked(b"a"))
  538. self.assertFalse(gc.is_tracked("a"))
  539. self.assertFalse(gc.is_tracked(bytearray(b"a")))
  540. self.assertFalse(gc.is_tracked(type))
  541. self.assertFalse(gc.is_tracked(int))
  542. self.assertFalse(gc.is_tracked(object))
  543. self.assertFalse(gc.is_tracked(object()))
  544. class UserClass:
  545. pass
  546. class UserInt(int):
  547. pass
  548. # Base class is object; no extra fields.
  549. class UserClassSlots:
  550. __slots__ = ()
  551. # Base class is fixed size larger than object; no extra fields.
  552. class UserFloatSlots(float):
  553. __slots__ = ()
  554. # Base class is variable size; no extra fields.
  555. class UserIntSlots(int):
  556. __slots__ = ()
  557. self.assertTrue(gc.is_tracked(gc))
  558. self.assertTrue(gc.is_tracked(UserClass))
  559. self.assertTrue(gc.is_tracked(UserClass()))
  560. self.assertTrue(gc.is_tracked(UserInt()))
  561. self.assertTrue(gc.is_tracked([]))
  562. self.assertTrue(gc.is_tracked(set()))
  563. self.assertTrue(gc.is_tracked(UserClassSlots()))
  564. self.assertTrue(gc.is_tracked(UserFloatSlots()))
  565. self.assertTrue(gc.is_tracked(UserIntSlots()))
  566. def test_is_finalized(self):
  567. # Objects not tracked by the always gc return false
  568. self.assertFalse(gc.is_finalized(3))
  569. storage = []
  570. class Lazarus:
  571. def __del__(self):
  572. storage.append(self)
  573. lazarus = Lazarus()
  574. self.assertFalse(gc.is_finalized(lazarus))
  575. del lazarus
  576. gc.collect()
  577. lazarus = storage.pop()
  578. self.assertTrue(gc.is_finalized(lazarus))
  579. def test_bug1055820b(self):
  580. # Corresponds to temp2b.py in the bug report.
  581. ouch = []
  582. def callback(ignored):
  583. ouch[:] = [wr() for wr in WRs]
  584. Cs = [C1055820(i) for i in range(2)]
  585. WRs = [weakref.ref(c, callback) for c in Cs]
  586. c = None
  587. gc.collect()
  588. self.assertEqual(len(ouch), 0)
  589. # Make the two instances trash, and collect again. The bug was that
  590. # the callback materialized a strong reference to an instance, but gc
  591. # cleared the instance's dict anyway.
  592. Cs = None
  593. gc.collect()
  594. self.assertEqual(len(ouch), 2) # else the callbacks didn't run
  595. for x in ouch:
  596. # If the callback resurrected one of these guys, the instance
  597. # would be damaged, with an empty __dict__.
  598. self.assertEqual(x, None)
  599. def test_bug21435(self):
  600. # This is a poor test - its only virtue is that it happened to
  601. # segfault on Tim's Windows box before the patch for 21435 was
  602. # applied. That's a nasty bug relying on specific pieces of cyclic
  603. # trash appearing in exactly the right order in finalize_garbage()'s
  604. # input list.
  605. # But there's no reliable way to force that order from Python code,
  606. # so over time chances are good this test won't really be testing much
  607. # of anything anymore. Still, if it blows up, there's _some_
  608. # problem ;-)
  609. gc.collect()
  610. class A:
  611. pass
  612. class B:
  613. def __init__(self, x):
  614. self.x = x
  615. def __del__(self):
  616. self.attr = None
  617. def do_work():
  618. a = A()
  619. b = B(A())
  620. a.attr = b
  621. b.attr = a
  622. do_work()
  623. gc.collect() # this blows up (bad C pointer) when it fails
  624. @cpython_only
  625. @requires_subprocess()
  626. def test_garbage_at_shutdown(self):
  627. import subprocess
  628. code = """if 1:
  629. import gc
  630. import _testcapi
  631. @_testcapi.with_tp_del
  632. class X:
  633. def __init__(self, name):
  634. self.name = name
  635. def __repr__(self):
  636. return "<X %%r>" %% self.name
  637. def __tp_del__(self):
  638. pass
  639. x = X('first')
  640. x.x = x
  641. x.y = X('second')
  642. del x
  643. gc.set_debug(%s)
  644. """
  645. def run_command(code):
  646. p = subprocess.Popen([sys.executable, "-Wd", "-c", code],
  647. stdout=subprocess.PIPE,
  648. stderr=subprocess.PIPE)
  649. stdout, stderr = p.communicate()
  650. p.stdout.close()
  651. p.stderr.close()
  652. self.assertEqual(p.returncode, 0)
  653. self.assertEqual(stdout, b"")
  654. return stderr
  655. stderr = run_command(code % "0")
  656. self.assertIn(b"ResourceWarning: gc: 2 uncollectable objects at "
  657. b"shutdown; use", stderr)
  658. self.assertNotIn(b"<X 'first'>", stderr)
  659. # With DEBUG_UNCOLLECTABLE, the garbage list gets printed
  660. stderr = run_command(code % "gc.DEBUG_UNCOLLECTABLE")
  661. self.assertIn(b"ResourceWarning: gc: 2 uncollectable objects at "
  662. b"shutdown", stderr)
  663. self.assertTrue(
  664. (b"[<X 'first'>, <X 'second'>]" in stderr) or
  665. (b"[<X 'second'>, <X 'first'>]" in stderr), stderr)
  666. # With DEBUG_SAVEALL, no additional message should get printed
  667. # (because gc.garbage also contains normally reclaimable cyclic
  668. # references, and its elements get printed at runtime anyway).
  669. stderr = run_command(code % "gc.DEBUG_SAVEALL")
  670. self.assertNotIn(b"uncollectable objects at shutdown", stderr)
  671. def test_gc_main_module_at_shutdown(self):
  672. # Create a reference cycle through the __main__ module and check
  673. # it gets collected at interpreter shutdown.
  674. code = """if 1:
  675. class C:
  676. def __del__(self):
  677. print('__del__ called')
  678. l = [C()]
  679. l.append(l)
  680. """
  681. rc, out, err = assert_python_ok('-c', code)
  682. self.assertEqual(out.strip(), b'__del__ called')
  683. def test_gc_ordinary_module_at_shutdown(self):
  684. # Same as above, but with a non-__main__ module.
  685. with temp_dir() as script_dir:
  686. module = """if 1:
  687. class C:
  688. def __del__(self):
  689. print('__del__ called')
  690. l = [C()]
  691. l.append(l)
  692. """
  693. code = """if 1:
  694. import sys
  695. sys.path.insert(0, %r)
  696. import gctest
  697. """ % (script_dir,)
  698. make_script(script_dir, 'gctest', module)
  699. rc, out, err = assert_python_ok('-c', code)
  700. self.assertEqual(out.strip(), b'__del__ called')
  701. def test_global_del_SystemExit(self):
  702. code = """if 1:
  703. class ClassWithDel:
  704. def __del__(self):
  705. print('__del__ called')
  706. a = ClassWithDel()
  707. a.link = a
  708. raise SystemExit(0)"""
  709. self.addCleanup(unlink, TESTFN)
  710. with open(TESTFN, 'w', encoding="utf-8") as script:
  711. script.write(code)
  712. rc, out, err = assert_python_ok(TESTFN)
  713. self.assertEqual(out.strip(), b'__del__ called')
  714. def test_get_stats(self):
  715. stats = gc.get_stats()
  716. self.assertEqual(len(stats), 3)
  717. for st in stats:
  718. self.assertIsInstance(st, dict)
  719. self.assertEqual(set(st),
  720. {"collected", "collections", "uncollectable"})
  721. self.assertGreaterEqual(st["collected"], 0)
  722. self.assertGreaterEqual(st["collections"], 0)
  723. self.assertGreaterEqual(st["uncollectable"], 0)
  724. # Check that collection counts are incremented correctly
  725. if gc.isenabled():
  726. self.addCleanup(gc.enable)
  727. gc.disable()
  728. old = gc.get_stats()
  729. gc.collect(0)
  730. new = gc.get_stats()
  731. self.assertEqual(new[0]["collections"], old[0]["collections"] + 1)
  732. self.assertEqual(new[1]["collections"], old[1]["collections"])
  733. self.assertEqual(new[2]["collections"], old[2]["collections"])
  734. gc.collect(2)
  735. new = gc.get_stats()
  736. self.assertEqual(new[0]["collections"], old[0]["collections"] + 1)
  737. self.assertEqual(new[1]["collections"], old[1]["collections"])
  738. self.assertEqual(new[2]["collections"], old[2]["collections"] + 1)
  739. 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. def test_get_objects(self):
  745. gc.collect()
  746. l = []
  747. l.append(l)
  748. self.assertTrue(
  749. any(l is element for element in gc.get_objects(generation=0))
  750. )
  751. self.assertFalse(
  752. any(l is element for element in gc.get_objects(generation=1))
  753. )
  754. self.assertFalse(
  755. any(l is element for element in gc.get_objects(generation=2))
  756. )
  757. gc.collect(generation=0)
  758. self.assertFalse(
  759. any(l is element for element in gc.get_objects(generation=0))
  760. )
  761. self.assertTrue(
  762. any(l is element for element in gc.get_objects(generation=1))
  763. )
  764. self.assertFalse(
  765. any(l is element for element in gc.get_objects(generation=2))
  766. )
  767. gc.collect(generation=1)
  768. self.assertFalse(
  769. any(l is element for element in gc.get_objects(generation=0))
  770. )
  771. self.assertFalse(
  772. any(l is element for element in gc.get_objects(generation=1))
  773. )
  774. self.assertTrue(
  775. any(l is element for element in gc.get_objects(generation=2))
  776. )
  777. gc.collect(generation=2)
  778. self.assertFalse(
  779. any(l is element for element in gc.get_objects(generation=0))
  780. )
  781. self.assertFalse(
  782. any(l is element for element in gc.get_objects(generation=1))
  783. )
  784. self.assertTrue(
  785. any(l is element for element in gc.get_objects(generation=2))
  786. )
  787. del l
  788. gc.collect()
  789. def test_get_objects_arguments(self):
  790. gc.collect()
  791. self.assertEqual(len(gc.get_objects()),
  792. len(gc.get_objects(generation=None)))
  793. self.assertRaises(ValueError, gc.get_objects, 1000)
  794. self.assertRaises(ValueError, gc.get_objects, -1000)
  795. self.assertRaises(TypeError, gc.get_objects, "1")
  796. self.assertRaises(TypeError, gc.get_objects, 1.234)
  797. def test_resurrection_only_happens_once_per_object(self):
  798. class A: # simple self-loop
  799. def __init__(self):
  800. self.me = self
  801. class Lazarus(A):
  802. resurrected = 0
  803. resurrected_instances = []
  804. def __del__(self):
  805. Lazarus.resurrected += 1
  806. Lazarus.resurrected_instances.append(self)
  807. gc.collect()
  808. gc.disable()
  809. # We start with 0 resurrections
  810. laz = Lazarus()
  811. self.assertEqual(Lazarus.resurrected, 0)
  812. # Deleting the instance and triggering a collection
  813. # resurrects the object
  814. del laz
  815. gc.collect()
  816. self.assertEqual(Lazarus.resurrected, 1)
  817. self.assertEqual(len(Lazarus.resurrected_instances), 1)
  818. # Clearing the references and forcing a collection
  819. # should not resurrect the object again.
  820. Lazarus.resurrected_instances.clear()
  821. self.assertEqual(Lazarus.resurrected, 1)
  822. gc.collect()
  823. self.assertEqual(Lazarus.resurrected, 1)
  824. gc.enable()
  825. def test_resurrection_is_transitive(self):
  826. class Cargo:
  827. def __init__(self):
  828. self.me = self
  829. class Lazarus:
  830. resurrected_instances = []
  831. def __del__(self):
  832. Lazarus.resurrected_instances.append(self)
  833. gc.collect()
  834. gc.disable()
  835. laz = Lazarus()
  836. cargo = Cargo()
  837. cargo_id = id(cargo)
  838. # Create a cycle between cargo and laz
  839. laz.cargo = cargo
  840. cargo.laz = laz
  841. # Drop the references, force a collection and check that
  842. # everything was resurrected.
  843. del laz, cargo
  844. gc.collect()
  845. self.assertEqual(len(Lazarus.resurrected_instances), 1)
  846. instance = Lazarus.resurrected_instances.pop()
  847. self.assertTrue(hasattr(instance, "cargo"))
  848. self.assertEqual(id(instance.cargo), cargo_id)
  849. gc.collect()
  850. gc.enable()
  851. def test_resurrection_does_not_block_cleanup_of_other_objects(self):
  852. # When a finalizer resurrects objects, stats were reporting them as
  853. # having been collected. This affected both collect()'s return
  854. # value and the dicts returned by get_stats().
  855. N = 100
  856. class A: # simple self-loop
  857. def __init__(self):
  858. self.me = self
  859. class Z(A): # resurrecting __del__
  860. def __del__(self):
  861. zs.append(self)
  862. zs = []
  863. def getstats():
  864. d = gc.get_stats()[-1]
  865. return d['collected'], d['uncollectable']
  866. gc.collect()
  867. gc.disable()
  868. # No problems if just collecting A() instances.
  869. oldc, oldnc = getstats()
  870. for i in range(N):
  871. A()
  872. t = gc.collect()
  873. c, nc = getstats()
  874. self.assertEqual(t, N) # instance objects
  875. self.assertEqual(c - oldc, N)
  876. self.assertEqual(nc - oldnc, 0)
  877. # But Z() is not actually collected.
  878. oldc, oldnc = c, nc
  879. Z()
  880. # Nothing is collected - Z() is merely resurrected.
  881. t = gc.collect()
  882. c, nc = getstats()
  883. self.assertEqual(t, 0)
  884. self.assertEqual(c - oldc, 0)
  885. self.assertEqual(nc - oldnc, 0)
  886. # Z() should not prevent anything else from being collected.
  887. oldc, oldnc = c, nc
  888. for i in range(N):
  889. A()
  890. Z()
  891. t = gc.collect()
  892. c, nc = getstats()
  893. self.assertEqual(t, N)
  894. self.assertEqual(c - oldc, N)
  895. self.assertEqual(nc - oldnc, 0)
  896. # The A() trash should have been reclaimed already but the
  897. # 2 copies of Z are still in zs (and the associated dicts).
  898. oldc, oldnc = c, nc
  899. zs.clear()
  900. t = gc.collect()
  901. c, nc = getstats()
  902. self.assertEqual(t, 2)
  903. self.assertEqual(c - oldc, 2)
  904. self.assertEqual(nc - oldnc, 0)
  905. gc.enable()
  906. @unittest.skipIf(ContainerNoGC is None,
  907. 'requires ContainerNoGC extension type')
  908. def test_trash_weakref_clear(self):
  909. # Test that trash weakrefs are properly cleared (bpo-38006).
  910. #
  911. # Structure we are creating:
  912. #
  913. # Z <- Y <- A--+--> WZ -> C
  914. # ^ |
  915. # +--+
  916. # where:
  917. # WZ is a weakref to Z with callback C
  918. # Y doesn't implement tp_traverse
  919. # A contains a reference to itself, Y and WZ
  920. #
  921. # A, Y, Z, WZ are all trash. The GC doesn't know that Z is trash
  922. # because Y does not implement tp_traverse. To show the bug, WZ needs
  923. # to live long enough so that Z is deallocated before it. Then, if
  924. # gcmodule is buggy, when Z is being deallocated, C will run.
  925. #
  926. # To ensure WZ lives long enough, we put it in a second reference
  927. # cycle. That trick only works due to the ordering of the GC prev/next
  928. # linked lists. So, this test is a bit fragile.
  929. #
  930. # The bug reported in bpo-38006 is caused because the GC did not
  931. # clear WZ before starting the process of calling tp_clear on the
  932. # trash. Normally, handle_weakrefs() would find the weakref via Z and
  933. # clear it. However, since the GC cannot find Z, WR is not cleared and
  934. # it can execute during delete_garbage(). That can lead to disaster
  935. # since the callback might tinker with objects that have already had
  936. # tp_clear called on them (leaving them in possibly invalid states).
  937. callback = unittest.mock.Mock()
  938. class A:
  939. __slots__ = ['a', 'y', 'wz']
  940. class Z:
  941. pass
  942. # setup required object graph, as described above
  943. a = A()
  944. a.a = a
  945. a.y = ContainerNoGC(Z())
  946. a.wz = weakref.ref(a.y.value, callback)
  947. # create second cycle to keep WZ alive longer
  948. wr_cycle = [a.wz]
  949. wr_cycle.append(wr_cycle)
  950. # ensure trash unrelated to this test is gone
  951. gc.collect()
  952. gc.disable()
  953. # release references and create trash
  954. del a, wr_cycle
  955. gc.collect()
  956. # if called, it means there is a bug in the GC. The weakref should be
  957. # cleared before Z dies.
  958. callback.assert_not_called()
  959. gc.enable()
  960. class GCCallbackTests(unittest.TestCase):
  961. def setUp(self):
  962. # Save gc state and disable it.
  963. self.enabled = gc.isenabled()
  964. gc.disable()
  965. self.debug = gc.get_debug()
  966. gc.set_debug(0)
  967. gc.callbacks.append(self.cb1)
  968. gc.callbacks.append(self.cb2)
  969. self.othergarbage = []
  970. def tearDown(self):
  971. # Restore gc state
  972. del self.visit
  973. gc.callbacks.remove(self.cb1)
  974. gc.callbacks.remove(self.cb2)
  975. gc.set_debug(self.debug)
  976. if self.enabled:
  977. gc.enable()
  978. # destroy any uncollectables
  979. gc.collect()
  980. for obj in gc.garbage:
  981. if isinstance(obj, Uncollectable):
  982. obj.partner = None
  983. del gc.garbage[:]
  984. del self.othergarbage
  985. gc.collect()
  986. def preclean(self):
  987. # Remove all fluff from the system. Invoke this function
  988. # manually rather than through self.setUp() for maximum
  989. # safety.
  990. self.visit = []
  991. gc.collect()
  992. garbage, gc.garbage[:] = gc.garbage[:], []
  993. self.othergarbage.append(garbage)
  994. self.visit = []
  995. def cb1(self, phase, info):
  996. self.visit.append((1, phase, dict(info)))
  997. def cb2(self, phase, info):
  998. self.visit.append((2, phase, dict(info)))
  999. if phase == "stop" and hasattr(self, "cleanup"):
  1000. # Clean Uncollectable from garbage
  1001. uc = [e for e in gc.garbage if isinstance(e, Uncollectable)]
  1002. gc.garbage[:] = [e for e in gc.garbage
  1003. if not isinstance(e, Uncollectable)]
  1004. for e in uc:
  1005. e.partner = None
  1006. def test_collect(self):
  1007. self.preclean()
  1008. gc.collect()
  1009. # Algorithmically verify the contents of self.visit
  1010. # because it is long and tortuous.
  1011. # Count the number of visits to each callback
  1012. n = [v[0] for v in self.visit]
  1013. n1 = [i for i in n if i == 1]
  1014. n2 = [i for i in n if i == 2]
  1015. self.assertEqual(n1, [1]*2)
  1016. self.assertEqual(n2, [2]*2)
  1017. # Count that we got the right number of start and stop callbacks.
  1018. n = [v[1] for v in self.visit]
  1019. n1 = [i for i in n if i == "start"]
  1020. n2 = [i for i in n if i == "stop"]
  1021. self.assertEqual(n1, ["start"]*2)
  1022. self.assertEqual(n2, ["stop"]*2)
  1023. # Check that we got the right info dict for all callbacks
  1024. for v in self.visit:
  1025. info = v[2]
  1026. self.assertTrue("generation" in info)
  1027. self.assertTrue("collected" in info)
  1028. self.assertTrue("uncollectable" in info)
  1029. def test_collect_generation(self):
  1030. self.preclean()
  1031. gc.collect(2)
  1032. for v in self.visit:
  1033. info = v[2]
  1034. self.assertEqual(info["generation"], 2)
  1035. @cpython_only
  1036. def test_collect_garbage(self):
  1037. self.preclean()
  1038. # Each of these cause two objects to be garbage:
  1039. Uncollectable()
  1040. Uncollectable()
  1041. C1055820(666)
  1042. gc.collect()
  1043. for v in self.visit:
  1044. if v[1] != "stop":
  1045. continue
  1046. info = v[2]
  1047. self.assertEqual(info["collected"], 1)
  1048. self.assertEqual(info["uncollectable"], 4)
  1049. # We should now have the Uncollectables in gc.garbage
  1050. self.assertEqual(len(gc.garbage), 4)
  1051. for e in gc.garbage:
  1052. self.assertIsInstance(e, Uncollectable)
  1053. # Now, let our callback handle the Uncollectable instances
  1054. self.cleanup=True
  1055. self.visit = []
  1056. gc.garbage[:] = []
  1057. gc.collect()
  1058. for v in self.visit:
  1059. if v[1] != "stop":
  1060. continue
  1061. info = v[2]
  1062. self.assertEqual(info["collected"], 0)
  1063. self.assertEqual(info["uncollectable"], 2)
  1064. # Uncollectables should be gone
  1065. self.assertEqual(len(gc.garbage), 0)
  1066. @unittest.skipIf(BUILD_WITH_NDEBUG,
  1067. 'built with -NDEBUG')
  1068. def test_refcount_errors(self):
  1069. self.preclean()
  1070. # Verify the "handling" of objects with broken refcounts
  1071. # Skip the test if ctypes is not available
  1072. import_module("ctypes")
  1073. import subprocess
  1074. code = textwrap.dedent('''
  1075. from test.support import gc_collect, SuppressCrashReport
  1076. a = [1, 2, 3]
  1077. b = [a]
  1078. # Avoid coredump when Py_FatalError() calls abort()
  1079. SuppressCrashReport().__enter__()
  1080. # Simulate the refcount of "a" being too low (compared to the
  1081. # references held on it by live data), but keeping it above zero
  1082. # (to avoid deallocating it):
  1083. import ctypes
  1084. ctypes.pythonapi.Py_DecRef(ctypes.py_object(a))
  1085. # The garbage collector should now have a fatal error
  1086. # when it reaches the broken object
  1087. gc_collect()
  1088. ''')
  1089. p = subprocess.Popen([sys.executable, "-c", code],
  1090. stdout=subprocess.PIPE,
  1091. stderr=subprocess.PIPE)
  1092. stdout, stderr = p.communicate()
  1093. p.stdout.close()
  1094. p.stderr.close()
  1095. # Verify that stderr has a useful error message:
  1096. self.assertRegex(stderr,
  1097. br'gcmodule\.c:[0-9]+: gc_decref: Assertion "gc_get_refs\(g\) > 0" failed.')
  1098. self.assertRegex(stderr,
  1099. br'refcount is too small')
  1100. # "address : 0x7fb5062efc18"
  1101. # "address : 7FB5062EFC18"
  1102. address_regex = br'[0-9a-fA-Fx]+'
  1103. self.assertRegex(stderr,
  1104. br'object address : ' + address_regex)
  1105. self.assertRegex(stderr,
  1106. br'object refcount : 1')
  1107. self.assertRegex(stderr,
  1108. br'object type : ' + address_regex)
  1109. self.assertRegex(stderr,
  1110. br'object type name: list')
  1111. self.assertRegex(stderr,
  1112. br'object repr : \[1, 2, 3\]')
  1113. class GCTogglingTests(unittest.TestCase):
  1114. def setUp(self):
  1115. gc.enable()
  1116. def tearDown(self):
  1117. gc.disable()
  1118. def test_bug1055820c(self):
  1119. # Corresponds to temp2c.py in the bug report. This is pretty
  1120. # elaborate.
  1121. c0 = C1055820(0)
  1122. # Move c0 into generation 2.
  1123. gc.collect()
  1124. c1 = C1055820(1)
  1125. c1.keep_c0_alive = c0
  1126. del c0.loop # now only c1 keeps c0 alive
  1127. c2 = C1055820(2)
  1128. c2wr = weakref.ref(c2) # no callback!
  1129. ouch = []
  1130. def callback(ignored):
  1131. ouch[:] = [c2wr()]
  1132. # The callback gets associated with a wr on an object in generation 2.
  1133. c0wr = weakref.ref(c0, callback)
  1134. c0 = c1 = c2 = None
  1135. # What we've set up: c0, c1, and c2 are all trash now. c0 is in
  1136. # generation 2. The only thing keeping it alive is that c1 points to
  1137. # it. c1 and c2 are in generation 0, and are in self-loops. There's a
  1138. # global weakref to c2 (c2wr), but that weakref has no callback.
  1139. # There's also a global weakref to c0 (c0wr), and that does have a
  1140. # callback, and that callback references c2 via c2wr().
  1141. #
  1142. # c0 has a wr with callback, which references c2wr
  1143. # ^
  1144. # |
  1145. # | Generation 2 above dots
  1146. #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . .
  1147. # | Generation 0 below dots
  1148. # |
  1149. # |
  1150. # ^->c1 ^->c2 has a wr but no callback
  1151. # | | | |
  1152. # <--v <--v
  1153. #
  1154. # So this is the nightmare: when generation 0 gets collected, we see
  1155. # that c2 has a callback-free weakref, and c1 doesn't even have a
  1156. # weakref. Collecting generation 0 doesn't see c0 at all, and c0 is
  1157. # the only object that has a weakref with a callback. gc clears c1
  1158. # and c2. Clearing c1 has the side effect of dropping the refcount on
  1159. # c0 to 0, so c0 goes away (despite that it's in an older generation)
  1160. # and c0's wr callback triggers. That in turn materializes a reference
  1161. # to c2 via c2wr(), but c2 gets cleared anyway by gc.
  1162. # We want to let gc happen "naturally", to preserve the distinction
  1163. # between generations.
  1164. junk = []
  1165. i = 0
  1166. detector = GC_Detector()
  1167. while not detector.gc_happened:
  1168. i += 1
  1169. if i > 10000:
  1170. self.fail("gc didn't happen after 10000 iterations")
  1171. self.assertEqual(len(ouch), 0)
  1172. junk.append([]) # this will eventually trigger gc
  1173. self.assertEqual(len(ouch), 1) # else the callback wasn't invoked
  1174. for x in ouch:
  1175. # If the callback resurrected c2, the instance would be damaged,
  1176. # with an empty __dict__.
  1177. self.assertEqual(x, None)
  1178. def test_bug1055820d(self):
  1179. # Corresponds to temp2d.py in the bug report. This is very much like
  1180. # test_bug1055820c, but uses a __del__ method instead of a weakref
  1181. # callback to sneak in a resurrection of cyclic trash.
  1182. ouch = []
  1183. class D(C1055820):
  1184. def __del__(self):
  1185. ouch[:] = [c2wr()]
  1186. d0 = D(0)
  1187. # Move all the above into generation 2.
  1188. gc.collect()
  1189. c1 = C1055820(1)
  1190. c1.keep_d0_alive = d0
  1191. del d0.loop # now only c1 keeps d0 alive
  1192. c2 = C1055820(2)
  1193. c2wr = weakref.ref(c2) # no callback!
  1194. d0 = c1 = c2 = None
  1195. # What we've set up: d0, c1, and c2 are all trash now. d0 is in
  1196. # generation 2. The only thing keeping it alive is that c1 points to
  1197. # it. c1 and c2 are in generation 0, and are in self-loops. There's
  1198. # a global weakref to c2 (c2wr), but that weakref has no callback.
  1199. # There are no other weakrefs.
  1200. #
  1201. # d0 has a __del__ method that references c2wr
  1202. # ^
  1203. # |
  1204. # | Generation 2 above dots
  1205. #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . .
  1206. # | Generation 0 below dots
  1207. # |
  1208. # |
  1209. # ^->c1 ^->c2 has a wr but no callback
  1210. # | | | |
  1211. # <--v <--v
  1212. #
  1213. # So this is the nightmare: when generation 0 gets collected, we see
  1214. # that c2 has a callback-free weakref, and c1 doesn't even have a
  1215. # weakref. Collecting generation 0 doesn't see d0 at all. gc clears
  1216. # c1 and c2. Clearing c1 has the side effect of dropping the refcount
  1217. # on d0 to 0, so d0 goes away (despite that it's in an older
  1218. # generation) and d0's __del__ triggers. That in turn materializes
  1219. # a reference to c2 via c2wr(), but c2 gets cleared anyway by gc.
  1220. # We want to let gc happen "naturally", to preserve the distinction
  1221. # between generations.
  1222. detector = GC_Detector()
  1223. junk = []
  1224. i = 0
  1225. while not detector.gc_happened:
  1226. i += 1
  1227. if i > 10000:
  1228. self.fail("gc didn't happen after 10000 iterations")
  1229. self.assertEqual(len(ouch), 0)
  1230. junk.append([]) # this will eventually trigger gc
  1231. self.assertEqual(len(ouch), 1) # else __del__ wasn't invoked
  1232. for x in ouch:
  1233. # If __del__ resurrected c2, the instance would be damaged, with an
  1234. # empty __dict__.
  1235. self.assertEqual(x, None)
  1236. class PythonFinalizationTests(unittest.TestCase):
  1237. def test_ast_fini(self):
  1238. # bpo-44184: Regression test for subtype_dealloc() when deallocating
  1239. # an AST instance also destroy its AST type: subtype_dealloc() must
  1240. # not access the type memory after deallocating the instance, since
  1241. # the type memory can be freed as well. The test is also related to
  1242. # _PyAST_Fini() which clears references to AST types.
  1243. code = textwrap.dedent("""
  1244. import ast
  1245. import codecs
  1246. # Small AST tree to keep their AST types alive
  1247. tree = ast.parse("def f(x, y): return 2*x-y")
  1248. x = [tree]
  1249. x.append(x)
  1250. # Put the cycle somewhere to survive until the last GC collection.
  1251. # Codec search functions are only cleared at the end of
  1252. # interpreter_clear().
  1253. def search_func(encoding):
  1254. return None
  1255. search_func.a = x
  1256. codecs.register(search_func)
  1257. """)
  1258. assert_python_ok("-c", code)
  1259. def setUpModule():
  1260. global enabled, debug
  1261. enabled = gc.isenabled()
  1262. gc.disable()
  1263. assert not gc.isenabled()
  1264. debug = gc.get_debug()
  1265. gc.set_debug(debug & ~gc.DEBUG_LEAK) # this test is supposed to leak
  1266. gc.collect() # Delete 2nd generation garbage
  1267. def tearDownModule():
  1268. gc.set_debug(debug)
  1269. # test gc.enable() even if GC is disabled by default
  1270. if verbose:
  1271. print("restoring automatic collection")
  1272. # make sure to always test gc.enable()
  1273. gc.enable()
  1274. assert gc.isenabled()
  1275. if not enabled:
  1276. gc.disable()
  1277. if __name__ == "__main__":
  1278. unittest.main()