mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
Issue #19542: Fix bugs in WeakValueDictionary.setdefault() and WeakValueDictionary.pop()
when a GC collection happens in another thread. Original patch and report by Armin Rigo.
This commit is contained in:
parent
ca3263c50c
commit
c1ee488962
3 changed files with 53 additions and 5 deletions
|
@ -6,6 +6,7 @@ import weakref
|
|||
import operator
|
||||
import contextlib
|
||||
import copy
|
||||
import time
|
||||
|
||||
from test import support
|
||||
from test.support import script_helper
|
||||
|
@ -72,6 +73,29 @@ class TestBase(unittest.TestCase):
|
|||
self.cbcalled += 1
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def collect_in_thread(period=0.0001):
|
||||
"""
|
||||
Ensure GC collections happen in a different thread, at a high frequency.
|
||||
"""
|
||||
threading = support.import_module('threading')
|
||||
please_stop = False
|
||||
|
||||
def collect():
|
||||
while not please_stop:
|
||||
time.sleep(period)
|
||||
gc.collect()
|
||||
|
||||
with support.disable_gc():
|
||||
t = threading.Thread(target=collect)
|
||||
t.start()
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
please_stop = True
|
||||
t.join()
|
||||
|
||||
|
||||
class ReferencesTestCase(TestBase):
|
||||
|
||||
def test_basic_ref(self):
|
||||
|
@ -1633,6 +1657,23 @@ class MappingTestCase(TestBase):
|
|||
dict = weakref.WeakKeyDictionary()
|
||||
self.assertRegex(repr(dict), '<WeakKeyDictionary at 0x.*>')
|
||||
|
||||
def test_threaded_weak_valued_setdefault(self):
|
||||
d = weakref.WeakValueDictionary()
|
||||
with collect_in_thread():
|
||||
for i in range(100000):
|
||||
x = d.setdefault(10, RefCycle())
|
||||
self.assertIsNot(x, None) # we never put None in there!
|
||||
del x
|
||||
|
||||
def test_threaded_weak_valued_pop(self):
|
||||
d = weakref.WeakValueDictionary()
|
||||
with collect_in_thread():
|
||||
for i in range(100000):
|
||||
d[10] = RefCycle()
|
||||
x = d.pop(10, 10)
|
||||
self.assertIsNot(x, None) # we never put None in there!
|
||||
|
||||
|
||||
from test import mapping_tests
|
||||
|
||||
class WeakValueDictionaryTestCase(mapping_tests.BasicTestMappingProtocol):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue