mirror of
https://github.com/python/cpython.git
synced 2025-10-31 21:51:50 +00:00
[3.14] gh-134908: Protect textiowrapper_iternext with critical section (gh-134910) (gh-135039)
The `textiowrapper_iternext` function called `_textiowrapper_writeflush`, but did not
use a critical section, making it racy in free-threaded builds.
(cherry picked from commit 44fb7c361c)
Co-authored-by: Duane Griffin <duaneg@dghda.com>
This commit is contained in:
parent
7ac461883d
commit
428b0ca114
3 changed files with 46 additions and 1 deletions
|
|
@ -1062,6 +1062,37 @@ def flush(self):
|
|||
# Silence destructor error
|
||||
R.flush = lambda self: None
|
||||
|
||||
@threading_helper.requires_working_threading()
|
||||
def test_write_readline_races(self):
|
||||
# gh-134908: Concurrent iteration over a file caused races
|
||||
thread_count = 2
|
||||
write_count = 100
|
||||
read_count = 100
|
||||
|
||||
def writer(file, barrier):
|
||||
barrier.wait()
|
||||
for _ in range(write_count):
|
||||
file.write("x")
|
||||
|
||||
def reader(file, barrier):
|
||||
barrier.wait()
|
||||
for _ in range(read_count):
|
||||
for line in file:
|
||||
self.assertEqual(line, "")
|
||||
|
||||
with self.open(os_helper.TESTFN, "w+") as f:
|
||||
barrier = threading.Barrier(thread_count + 1)
|
||||
reader = threading.Thread(target=reader, args=(f, barrier))
|
||||
writers = [threading.Thread(target=writer, args=(f, barrier))
|
||||
for _ in range(thread_count)]
|
||||
with threading_helper.catch_threading_exception() as cm:
|
||||
with threading_helper.start_threads(writers + [reader]):
|
||||
pass
|
||||
self.assertIsNone(cm.exc_type)
|
||||
|
||||
self.assertEqual(os.stat(os_helper.TESTFN).st_size,
|
||||
write_count * thread_count)
|
||||
|
||||
|
||||
class CIOTest(IOTest):
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue