mirror of
https://github.com/python/cpython.git
synced 2025-07-28 05:34:31 +00:00
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
aa66a968d4
commit
c4ad0345cf
4 changed files with 146 additions and 14 deletions
|
@ -86,9 +86,11 @@ except ImportError:
|
|||
from StringIO import StringIO
|
||||
|
||||
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))
|
||||
|
@ -286,10 +288,22 @@ class _fileobject(object):
|
|||
|
||||
def flush(self):
|
||||
if self._wbuf:
|
||||
buffer = "".join(self._wbuf)
|
||||
data = "".join(self._wbuf)
|
||||
self._wbuf = []
|
||||
self._wbuf_len = 0
|
||||
self._sock.sendall(buffer)
|
||||
buffer_size = max(self._rbufsize, self.default_bufsize)
|
||||
data_size = len(data)
|
||||
write_offset = 0
|
||||
try:
|
||||
while write_offset < data_size:
|
||||
self._sock.sendall(buffer(data, write_offset, buffer_size))
|
||||
write_offset += buffer_size
|
||||
finally:
|
||||
if write_offset < data_size:
|
||||
remainder = data[write_offset:]
|
||||
del data # explicit free
|
||||
self._wbuf.append(remainder)
|
||||
self._wbuf_len = len(remainder)
|
||||
|
||||
def fileno(self):
|
||||
return self._sock.fileno()
|
||||
|
@ -329,7 +343,12 @@ class _fileobject(object):
|
|||
# Read until EOF
|
||||
self._rbuf = StringIO() # reset _rbuf. we consume it via buf.
|
||||
while True:
|
||||
data = self._sock.recv(rbufsize)
|
||||
try:
|
||||
data = self._sock.recv(rbufsize)
|
||||
except error, e:
|
||||
if e[0] == EINTR:
|
||||
continue
|
||||
raise
|
||||
if not data:
|
||||
break
|
||||
buf.write(data)
|
||||
|
@ -353,7 +372,12 @@ class _fileobject(object):
|
|||
# than that. The returned data string is short lived
|
||||
# as we copy it into a StringIO and free it. This avoids
|
||||
# fragmentation issues on many platforms.
|
||||
data = self._sock.recv(left)
|
||||
try:
|
||||
data = self._sock.recv(left)
|
||||
except error, e:
|
||||
if e[0] == EINTR:
|
||||
continue
|
||||
raise
|
||||
if not data:
|
||||
break
|
||||
n = len(data)
|
||||
|
@ -396,17 +420,31 @@ class _fileobject(object):
|
|||
self._rbuf = StringIO() # reset _rbuf. we consume it via buf.
|
||||
data = None
|
||||
recv = self._sock.recv
|
||||
while data != "\n":
|
||||
data = recv(1)
|
||||
if not data:
|
||||
break
|
||||
buffers.append(data)
|
||||
while True:
|
||||
try:
|
||||
while data != "\n":
|
||||
data = recv(1)
|
||||
if not data:
|
||||
break
|
||||
buffers.append(data)
|
||||
except error, e:
|
||||
# The try..except to catch EINTR was moved outside the
|
||||
# recv loop to avoid the per byte overhead.
|
||||
if e[0] == EINTR:
|
||||
continue
|
||||
raise
|
||||
break
|
||||
return "".join(buffers)
|
||||
|
||||
buf.seek(0, 2) # seek end
|
||||
self._rbuf = StringIO() # reset _rbuf. we consume it via buf.
|
||||
while True:
|
||||
data = self._sock.recv(self._rbufsize)
|
||||
try:
|
||||
data = self._sock.recv(self._rbufsize)
|
||||
except error, e:
|
||||
if e[0] == EINTR:
|
||||
continue
|
||||
raise
|
||||
if not data:
|
||||
break
|
||||
nl = data.find('\n')
|
||||
|
@ -430,7 +468,12 @@ class _fileobject(object):
|
|||
return rv
|
||||
self._rbuf = StringIO() # reset _rbuf. we consume it via buf.
|
||||
while True:
|
||||
data = self._sock.recv(self._rbufsize)
|
||||
try:
|
||||
data = self._sock.recv(self._rbufsize)
|
||||
except error, e:
|
||||
if e[0] == EINTR:
|
||||
continue
|
||||
raise
|
||||
if not data:
|
||||
break
|
||||
left = size - buf_len
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue