diff options
| author | Jean-Paul Calderone <exarkun@divmod.com> | 2010-05-23 15:22:08 (GMT) |
|---|---|---|
| committer | Jean-Paul Calderone <exarkun@divmod.com> | 2010-05-23 15:22:08 (GMT) |
| commit | c28d554db8278d7346ff28da2defb59d413f857e (patch) | |
| tree | f55c0d609f0b01b21aee03df27dac8b10bde6e5b /Lib/socket.py | |
| parent | add85daa876ecd0f7e5b035ec065f933908761fb (diff) | |
| download | cpython-c28d554db8278d7346ff28da2defb59d413f857e.zip cpython-c28d554db8278d7346ff28da2defb59d413f857e.tar.gz cpython-c28d554db8278d7346ff28da2defb59d413f857e.tar.bz2 | |
Merged revisions 74426 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r74426 | gregory.p.smith | 2009-08-13 14:54:50 -0400 (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.
........
Diffstat (limited to 'Lib/socket.py')
| -rw-r--r-- | Lib/socket.py | 69 |
1 files changed, 56 insertions, 13 deletions
diff --git a/Lib/socket.py b/Lib/socket.py index 596e30c..98ab2dc 100644 --- a/Lib/socket.py +++ b/Lib/socket.py @@ -84,9 +84,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)) @@ -280,10 +282,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() @@ -326,7 +340,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) @@ -350,7 +369,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) @@ -393,17 +417,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') @@ -427,7 +465,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 |
