mirror of
https://github.com/python/cpython.git
synced 2025-07-30 06:34:15 +00:00
bpo-42536: GC track recycled tuples (GH-23623) (GH-23651)
Several built-in and standard library types now ensure that their internal result tuples are always tracked by the garbage collector:
- collections.OrderedDict.items
- dict.items
- enumerate
- functools.reduce
- itertools.combinations
- itertools.combinations_with_replacement
- itertools.permutations
- itertools.product
- itertools.zip_longest
- zip
Previously, they could have become untracked by a prior garbage collection.
(cherry picked from commit 226a012d1c
)
This commit is contained in:
parent
e9a6dcdefa
commit
60463e8e4f
12 changed files with 192 additions and 0 deletions
|
@ -12,6 +12,8 @@ from functools import reduce
|
|||
import sys
|
||||
import struct
|
||||
import threading
|
||||
import gc
|
||||
|
||||
maxsize = support.MAX_Py_ssize_t
|
||||
minsize = -maxsize-1
|
||||
|
||||
|
@ -1554,6 +1556,51 @@ class TestBasicOps(unittest.TestCase):
|
|||
self.assertRaises(StopIteration, next, f(lambda x:x, []))
|
||||
self.assertRaises(StopIteration, next, f(lambda x:x, StopNow()))
|
||||
|
||||
@support.cpython_only
|
||||
def test_combinations_result_gc(self):
|
||||
# bpo-42536: combinations's tuple-reuse speed trick breaks the GC's
|
||||
# assumptions about what can be untracked. Make sure we re-track result
|
||||
# tuples whenever we reuse them.
|
||||
it = combinations([None, []], 1)
|
||||
next(it)
|
||||
gc.collect()
|
||||
# That GC collection probably untracked the recycled internal result
|
||||
# tuple, which has the value (None,). Make sure it's re-tracked when
|
||||
# it's mutated and returned from __next__:
|
||||
self.assertTrue(gc.is_tracked(next(it)))
|
||||
|
||||
@support.cpython_only
|
||||
def test_combinations_with_replacement_result_gc(self):
|
||||
# Ditto for combinations_with_replacement.
|
||||
it = combinations_with_replacement([None, []], 1)
|
||||
next(it)
|
||||
gc.collect()
|
||||
self.assertTrue(gc.is_tracked(next(it)))
|
||||
|
||||
@support.cpython_only
|
||||
def test_permutations_result_gc(self):
|
||||
# Ditto for permutations.
|
||||
it = permutations([None, []], 1)
|
||||
next(it)
|
||||
gc.collect()
|
||||
self.assertTrue(gc.is_tracked(next(it)))
|
||||
|
||||
@support.cpython_only
|
||||
def test_product_result_gc(self):
|
||||
# Ditto for product.
|
||||
it = product([None, []])
|
||||
next(it)
|
||||
gc.collect()
|
||||
self.assertTrue(gc.is_tracked(next(it)))
|
||||
|
||||
@support.cpython_only
|
||||
def test_zip_longest_result_gc(self):
|
||||
# Ditto for zip_longest.
|
||||
it = zip_longest([[]])
|
||||
gc.collect()
|
||||
self.assertTrue(gc.is_tracked(next(it)))
|
||||
|
||||
|
||||
class TestExamples(unittest.TestCase):
|
||||
|
||||
def test_accumulate(self):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue