Issue #7322: Trying to read from a socket's file-like object after a timeout
occurred now raises an error instead of silently losing data. Patch by Ross Lagerwall.
This commit is contained in:
parent
fc1cf41911
commit
68e5c044e8
|
@ -257,6 +257,7 @@ class SocketIO(io.RawIOBase):
|
||||||
self._mode = mode
|
self._mode = mode
|
||||||
self._reading = "r" in mode
|
self._reading = "r" in mode
|
||||||
self._writing = "w" in mode
|
self._writing = "w" in mode
|
||||||
|
self._timeout_occurred = False
|
||||||
|
|
||||||
def readinto(self, b):
|
def readinto(self, b):
|
||||||
"""Read up to len(b) bytes into the writable buffer *b* and return
|
"""Read up to len(b) bytes into the writable buffer *b* and return
|
||||||
|
@ -268,9 +269,14 @@ class SocketIO(io.RawIOBase):
|
||||||
"""
|
"""
|
||||||
self._checkClosed()
|
self._checkClosed()
|
||||||
self._checkReadable()
|
self._checkReadable()
|
||||||
|
if self._timeout_occurred:
|
||||||
|
raise IOError("cannot read from timed out object")
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
return self._sock.recv_into(b)
|
return self._sock.recv_into(b)
|
||||||
|
except timeout:
|
||||||
|
self._timeout_occurred = True
|
||||||
|
raise
|
||||||
except error as e:
|
except error as e:
|
||||||
n = e.args[0]
|
n = e.args[0]
|
||||||
if n == EINTR:
|
if n == EINTR:
|
||||||
|
|
|
@ -1109,6 +1109,23 @@ class FileObjectClassTestCase(SocketConnectedTest):
|
||||||
self.write_file = None
|
self.write_file = None
|
||||||
SocketConnectedTest.clientTearDown(self)
|
SocketConnectedTest.clientTearDown(self)
|
||||||
|
|
||||||
|
def testReadAfterTimeout(self):
|
||||||
|
# Issue #7322: A file object must disallow further reads
|
||||||
|
# after a timeout has occurred.
|
||||||
|
self.cli_conn.settimeout(1)
|
||||||
|
self.read_file.read(3)
|
||||||
|
# First read raises a timeout
|
||||||
|
self.assertRaises(socket.timeout, self.read_file.read, 1)
|
||||||
|
# Second read is disallowed
|
||||||
|
with self.assertRaises(IOError) as ctx:
|
||||||
|
self.read_file.read(1)
|
||||||
|
self.assertIn("cannot read from timed out object", str(ctx.exception))
|
||||||
|
|
||||||
|
def _testReadAfterTimeout(self):
|
||||||
|
self.write_file.write(self.write_msg[0:3])
|
||||||
|
self.write_file.flush()
|
||||||
|
self.serv_finished.wait()
|
||||||
|
|
||||||
def testSmallRead(self):
|
def testSmallRead(self):
|
||||||
# Performing small file read test
|
# Performing small file read test
|
||||||
first_seg = self.read_file.read(len(self.read_msg)-3)
|
first_seg = self.read_file.read(len(self.read_msg)-3)
|
||||||
|
|
|
@ -35,6 +35,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #7322: Trying to read from a socket's file-like object after a timeout
|
||||||
|
occurred now raises an error instead of silently losing data.
|
||||||
|
|
||||||
- Issue 11291: poplib.POP no longer suppresses errors on quit().
|
- Issue 11291: poplib.POP no longer suppresses errors on quit().
|
||||||
|
|
||||||
- Issue 11177: asyncore's create_socket() arguments can now be omitted.
|
- Issue 11177: asyncore's create_socket() arguments can now be omitted.
|
||||||
|
|
Loading…
Reference in New Issue