Merged revisions 74426 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r74426 | gregory.p.smith | 2009-08-13 11:54:50 -0700 (Thu, 13 Aug 2009) | 4 lines Fix issue1628205: Socket file objects returned by socket.socket.makefile() now properly handles EINTR within the read, readline, write & flush methods. The socket.sendall() method now properly handles interrupted system calls. ........
This commit is contained in:
parent
960737de59
commit
aafdca895b
|
@ -49,9 +49,11 @@ from _socket import *
|
|||
import os, sys, io
|
||||
|
||||
try:
|
||||
from errno import EBADF
|
||||
import errno
|
||||
except ImportError:
|
||||
EBADF = 9
|
||||
errno = None
|
||||
EBADF = getattr(errno, 'EBADF', 9)
|
||||
EINTR = getattr(errno, 'EINTR', 4)
|
||||
|
||||
__all__ = ["getfqdn", "create_connection"]
|
||||
__all__.extend(os._get_exports_list(_socket))
|
||||
|
@ -212,7 +214,13 @@ class SocketIO(io.RawIOBase):
|
|||
def readinto(self, b):
|
||||
self._checkClosed()
|
||||
self._checkReadable()
|
||||
return self._sock.recv_into(b)
|
||||
while True:
|
||||
try:
|
||||
return self._sock.recv_into(b)
|
||||
except error as e:
|
||||
if e.args[0] == EINTR:
|
||||
continue
|
||||
raise
|
||||
|
||||
def write(self, b):
|
||||
self._checkClosed()
|
||||
|
|
|
@ -4,6 +4,7 @@ import unittest
|
|||
from test import support
|
||||
|
||||
import errno
|
||||
import io
|
||||
import socket
|
||||
import select
|
||||
import _thread as thread
|
||||
|
@ -906,6 +907,117 @@ class FileObjectClassTestCase(SocketConnectedTest):
|
|||
pass
|
||||
|
||||
|
||||
class FileObjectInterruptedTestCase(unittest.TestCase):
|
||||
"""Test that the file object correctly handles EINTR internally."""
|
||||
|
||||
class MockSocket(object):
|
||||
def __init__(self, recv_funcs=()):
|
||||
# A generator that returns callables that we'll call for each
|
||||
# call to recv().
|
||||
self._recv_step = iter(recv_funcs)
|
||||
|
||||
def recv_into(self, buffer):
|
||||
data = next(self._recv_step)()
|
||||
assert len(buffer) >= len(data)
|
||||
buffer[:len(data)] = data
|
||||
return len(data)
|
||||
|
||||
def _decref_socketios(self):
|
||||
pass
|
||||
|
||||
def _textiowrap_for_test(self, buffering=-1):
|
||||
raw = socket.SocketIO(self, "r")
|
||||
if buffering < 0:
|
||||
buffering = io.DEFAULT_BUFFER_SIZE
|
||||
if buffering == 0:
|
||||
return raw
|
||||
buffer = io.BufferedReader(raw, buffering)
|
||||
text = io.TextIOWrapper(buffer, None, None)
|
||||
text.mode = "rb"
|
||||
return text
|
||||
|
||||
@staticmethod
|
||||
def _raise_eintr():
|
||||
raise socket.error(errno.EINTR)
|
||||
|
||||
def _textiowrap_mock_socket(self, mock, buffering=-1):
|
||||
raw = socket.SocketIO(mock, "r")
|
||||
if buffering < 0:
|
||||
buffering = io.DEFAULT_BUFFER_SIZE
|
||||
if buffering == 0:
|
||||
return raw
|
||||
buffer = io.BufferedReader(raw, buffering)
|
||||
text = io.TextIOWrapper(buffer, None, None)
|
||||
text.mode = "rb"
|
||||
return text
|
||||
|
||||
def _test_readline(self, size=-1, buffering=-1):
|
||||
mock_sock = self.MockSocket(recv_funcs=[
|
||||
lambda : b"This is the first line\nAnd the sec",
|
||||
self._raise_eintr,
|
||||
lambda : b"ond line is here\n",
|
||||
lambda : b"",
|
||||
lambda : b"", # XXX(gps): io library does an extra EOF read
|
||||
])
|
||||
fo = mock_sock._textiowrap_for_test(buffering=buffering)
|
||||
self.assertEquals(fo.readline(size), "This is the first line\n")
|
||||
self.assertEquals(fo.readline(size), "And the second line is here\n")
|
||||
|
||||
def _test_read(self, size=-1, buffering=-1):
|
||||
mock_sock = self.MockSocket(recv_funcs=[
|
||||
lambda : b"This is the first line\nAnd the sec",
|
||||
self._raise_eintr,
|
||||
lambda : b"ond line is here\n",
|
||||
lambda : b"",
|
||||
lambda : b"", # XXX(gps): io library does an extra EOF read
|
||||
])
|
||||
expecting = (b"This is the first line\n"
|
||||
b"And the second line is here\n")
|
||||
fo = mock_sock._textiowrap_for_test(buffering=buffering)
|
||||
if buffering == 0:
|
||||
data = b''
|
||||
else:
|
||||
data = ''
|
||||
expecting = expecting.decode('utf8')
|
||||
while len(data) != len(expecting):
|
||||
part = fo.read(size)
|
||||
if not part:
|
||||
break
|
||||
data += part
|
||||
self.assertEquals(data, expecting)
|
||||
|
||||
def test_default(self):
|
||||
self._test_readline()
|
||||
self._test_readline(size=100)
|
||||
self._test_read()
|
||||
self._test_read(size=100)
|
||||
|
||||
def test_with_1k_buffer(self):
|
||||
self._test_readline(buffering=1024)
|
||||
self._test_readline(size=100, buffering=1024)
|
||||
self._test_read(buffering=1024)
|
||||
self._test_read(size=100, buffering=1024)
|
||||
|
||||
def _test_readline_no_buffer(self, size=-1):
|
||||
mock_sock = self.MockSocket(recv_funcs=[
|
||||
lambda : b"a",
|
||||
lambda : b"\n",
|
||||
lambda : b"B",
|
||||
self._raise_eintr,
|
||||
lambda : b"b",
|
||||
lambda : b"",
|
||||
])
|
||||
fo = mock_sock._textiowrap_for_test(buffering=0)
|
||||
self.assertEquals(fo.readline(size), b"a\n")
|
||||
self.assertEquals(fo.readline(size), b"Bb")
|
||||
|
||||
def test_no_buffer(self):
|
||||
self._test_readline_no_buffer()
|
||||
self._test_readline_no_buffer(size=4)
|
||||
self._test_read(buffering=0)
|
||||
self._test_read(size=100, buffering=0)
|
||||
|
||||
|
||||
class UnbufferedFileObjectClassTestCase(FileObjectClassTestCase):
|
||||
|
||||
"""Repeat the tests from FileObjectClassTestCase with bufsize==0.
|
||||
|
@ -1310,6 +1422,7 @@ def test_main():
|
|||
tests.extend([
|
||||
NonBlockingTCPTests,
|
||||
FileObjectClassTestCase,
|
||||
FileObjectInterruptedTestCase,
|
||||
UnbufferedFileObjectClassTestCase,
|
||||
LineBufferedFileObjectClassTestCase,
|
||||
SmallBufferedFileObjectClassTestCase,
|
||||
|
|
|
@ -194,6 +194,10 @@ C-API
|
|||
Library
|
||||
-------
|
||||
|
||||
- Issue #1628205: Socket file objects returned by socket.socket.makefile() now
|
||||
properly handles EINTR within the read, readline, write & flush methods.
|
||||
The socket.sendall() method now properly handles interrupted system calls.
|
||||
|
||||
- Issue #7471: Improve the performance of GzipFile's buffering mechanism,
|
||||
and make it implement the `io.BufferedIOBase` ABC to allow for further
|
||||
speedups by wrapping it in an `io.BufferedReader`. Patch by Nir Aides.
|
||||
|
|
Loading…
Reference in New Issue