mirror of
https://github.com/python/cpython.git
synced 2025-08-31 22:18:28 +00:00
bpo-31976: Fix race condition when flushing a file is slow. (#4331)
This commit is contained in:
parent
4652bf2acc
commit
9703f092ab
4 changed files with 58 additions and 8 deletions
|
@ -168,6 +168,22 @@ class PyMisbehavedRawIO(MisbehavedRawIO, pyio.RawIOBase):
|
|||
pass
|
||||
|
||||
|
||||
class SlowFlushRawIO(MockRawIO):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.in_flush = threading.Event()
|
||||
|
||||
def flush(self):
|
||||
self.in_flush.set()
|
||||
time.sleep(0.25)
|
||||
|
||||
class CSlowFlushRawIO(SlowFlushRawIO, io.RawIOBase):
|
||||
pass
|
||||
|
||||
class PySlowFlushRawIO(SlowFlushRawIO, pyio.RawIOBase):
|
||||
pass
|
||||
|
||||
|
||||
class CloseFailureIO(MockRawIO):
|
||||
closed = 0
|
||||
|
||||
|
@ -1726,6 +1742,18 @@ class BufferedWriterTest(unittest.TestCase, CommonBufferedTests):
|
|||
self.assertRaises(OSError, b.close) # exception not swallowed
|
||||
self.assertTrue(b.closed)
|
||||
|
||||
def test_slow_close_from_thread(self):
|
||||
# Issue #31976
|
||||
rawio = self.SlowFlushRawIO()
|
||||
bufio = self.tp(rawio, 8)
|
||||
t = threading.Thread(target=bufio.close)
|
||||
t.start()
|
||||
rawio.in_flush.wait()
|
||||
self.assertRaises(ValueError, bufio.write, b'spam')
|
||||
self.assertTrue(bufio.closed)
|
||||
t.join()
|
||||
|
||||
|
||||
|
||||
class CBufferedWriterTest(BufferedWriterTest, SizeofTest):
|
||||
tp = io.BufferedWriter
|
||||
|
@ -4085,7 +4113,8 @@ def load_tests(*args):
|
|||
# Put the namespaces of the IO module we are testing and some useful mock
|
||||
# classes in the __dict__ of each test.
|
||||
mocks = (MockRawIO, MisbehavedRawIO, MockFileIO, CloseFailureIO,
|
||||
MockNonBlockWriterIO, MockUnseekableIO, MockRawIOWithoutRead)
|
||||
MockNonBlockWriterIO, MockUnseekableIO, MockRawIOWithoutRead,
|
||||
SlowFlushRawIO)
|
||||
all_members = io.__all__ + ["IncrementalNewlineDecoder"]
|
||||
c_io_ns = {name : getattr(io, name) for name in all_members}
|
||||
py_io_ns = {name : getattr(pyio, name) for name in all_members}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue