diff options
author | benfogle <benfogle@gmail.com> | 2017-11-10 21:03:40 (GMT) |
---|---|---|
committer | Antoine Pitrou <pitrou@free.fr> | 2017-11-10 21:03:40 (GMT) |
commit | 9703f092abc0259926d88c7855afeae4a78afc7d (patch) | |
tree | d19e75bea4faacf58155861dd056f544a584f146 /Lib/test/test_io.py | |
parent | 4652bf2acc0d1ddabd224efabbfee0c3125da18b (diff) | |
download | cpython-9703f092abc0259926d88c7855afeae4a78afc7d.zip cpython-9703f092abc0259926d88c7855afeae4a78afc7d.tar.gz cpython-9703f092abc0259926d88c7855afeae4a78afc7d.tar.bz2 |
bpo-31976: Fix race condition when flushing a file is slow. (#4331)
Diffstat (limited to 'Lib/test/test_io.py')
-rw-r--r-- | Lib/test/test_io.py | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 3158729..2ac2e17 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -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} |