diff options
| -rw-r--r-- | AUTHORS | 1 | ||||
| -rw-r--r-- | eventlet/green/os.py | 25 | ||||
| -rw-r--r-- | eventlet/green/ssl.py | 11 | ||||
| -rw-r--r-- | eventlet/greenio.py | 16 | ||||
| -rw-r--r-- | eventlet/support/__init__.py | 7 |
5 files changed, 37 insertions, 23 deletions
@@ -93,3 +93,4 @@ Thanks To * David Goetz, wsgi: Allow minimum_chunk_size to be overriden on a per request basis * Dmitry Orlov, websocket: accept Upgrade: websocket (lowercase) * Zhang Hua, profile: accumulate results between runs (Bitbucket #162) +* Ramakrishnan G, greenio: consider EAGAIN error code like EWOULDBLOCK (Github #61) diff --git a/eventlet/green/os.py b/eventlet/green/os.py index e16041a..c80ca7f 100644 --- a/eventlet/green/os.py +++ b/eventlet/green/os.py @@ -3,7 +3,7 @@ import errno socket = __import__("socket") from eventlet import greenio -from eventlet.support import get_errno +from eventlet.support import EAGAIN_ALIASES, get_errno from eventlet import greenthread from eventlet import hubs from eventlet.patcher import slurp_properties @@ -11,12 +11,13 @@ from eventlet.patcher import slurp_properties __all__ = os_orig.__all__ __patched__ = ['fdopen', 'read', 'write', 'wait', 'waitpid'] -slurp_properties(os_orig, globals(), +slurp_properties(os_orig, globals(), ignore=__patched__, srckeys=dir(os_orig)) + def fdopen(fd, *args, **kw): """fdopen(fd [, mode='r' [, bufsize]]) -> file_object - + Return an open file object connected to a file descriptor.""" if not isinstance(fd, int): raise TypeError('fd should be int, not %r' % fd) @@ -25,16 +26,17 @@ def fdopen(fd, *args, **kw): except IOError as e: raise OSError(*e.args) + __original_read__ = os_orig.read def read(fd, n): """read(fd, buffersize) -> string - + Read a file descriptor.""" while True: try: return __original_read__(fd, n) except (OSError, IOError) as e: - if get_errno(e) != errno.EAGAIN: + if get_errno(e) not in EAGAIN_ALIASES: raise except socket.error as e: if get_errno(e) == errno.EPIPE: @@ -42,34 +44,37 @@ def read(fd, n): raise hubs.trampoline(fd, read=True) + __original_write__ = os_orig.write def write(fd, st): """write(fd, string) -> byteswritten - + Write a string to a file descriptor. """ while True: try: return __original_write__(fd, st) except (OSError, IOError) as e: - if get_errno(e) != errno.EAGAIN: + if get_errno(e) not in EAGAIN_ALIASES: raise except socket.error as e: if get_errno(e) != errno.EPIPE: raise hubs.trampoline(fd, write=True) - + + def wait(): """wait() -> (pid, status) - + Wait for completion of a child process.""" return waitpid(0,0) + __original_waitpid__ = os_orig.waitpid def waitpid(pid, options): """waitpid(...) waitpid(pid, options) -> (pid, status) - + Wait for completion of a given child process.""" if options & os_orig.WNOHANG != 0: return __original_waitpid__(pid, options) diff --git a/eventlet/green/ssl.py b/eventlet/green/ssl.py index 62fec77..00e6eeb 100644 --- a/eventlet/green/ssl.py +++ b/eventlet/green/ssl.py @@ -7,7 +7,7 @@ import sys import errno time = __import__('time') -from eventlet.support import get_errno +from eventlet.support import EAGAIN_ALIASES, get_errno from eventlet.hubs import trampoline from eventlet.greenio import set_nonblocking, GreenSocket, SOCKET_CLOSED, CONNECT_ERR, CONNECT_SUCCESS orig_socket = __import__('socket') @@ -21,6 +21,7 @@ else: __patched__ = ['SSLSocket', 'wrap_socket', 'sslwrap_simple'] + class GreenSSLSocket(__ssl.SSLSocket): """ This is a green version of the SSLSocket class from the ssl module added in 2.6. For documentation on it, please see the Python standard @@ -140,7 +141,7 @@ class GreenSSLSocket(__ssl.SSLSocket): except orig_socket.error as e: if self.act_non_blocking: raise - if get_errno(e) == errno.EWOULDBLOCK: + if get_errno(e) in EAGAIN_ALIASES: trampoline(self, write=True, timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out')) if get_errno(e) in SOCKET_CLOSED: @@ -163,7 +164,7 @@ class GreenSSLSocket(__ssl.SSLSocket): except orig_socket.error as e: if self.act_non_blocking: raise - if get_errno(e) == errno.EWOULDBLOCK: + if get_errno(e) in EAGAIN_ALIASES: trampoline(self, read=True, timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out')) if get_errno(e) in SOCKET_CLOSED: @@ -263,7 +264,7 @@ class GreenSSLSocket(__ssl.SSLSocket): set_nonblocking(newsock) break except orig_socket.error as e: - if get_errno(e) != errno.EWOULDBLOCK: + if get_errno(e) not in EAGAIN_ALIASES: raise trampoline(self, read=True, timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out')) @@ -282,8 +283,10 @@ class GreenSSLSocket(__ssl.SSLSocket): def dup(self): raise NotImplementedError("Can't dup an ssl object") + SSLSocket = GreenSSLSocket + def wrap_socket(sock, *a, **kw): return GreenSSLSocket(sock, *a, **kw) diff --git a/eventlet/greenio.py b/eventlet/greenio.py index 251a30d..60dd1cb 100644 --- a/eventlet/greenio.py +++ b/eventlet/greenio.py @@ -1,4 +1,4 @@ -from eventlet.support import get_errno, six +from eventlet.support import EAGAIN_ALIASES, get_errno, six from eventlet.hubs import trampoline BUFFER_SIZE = 4096 @@ -13,7 +13,7 @@ import warnings __all__ = ['GreenSocket', 'GreenPipe', 'shutdown_safe'] -CONNECT_ERR = set((errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK)) +CONNECT_ERR = set((errno.EINPROGRESS, errno.EALREADY) + EAGAIN_ALIASES) CONNECT_SUCCESS = set((0, errno.EISCONN)) if sys.platform[:3] == "win": CONNECT_ERR.add(errno.WSAEINVAL) # Bug 67 @@ -53,19 +53,19 @@ def socket_accept(descriptor): try: return descriptor.accept() except socket.error as e: - if get_errno(e) == errno.EWOULDBLOCK: + if get_errno(e) in EAGAIN_ALIASES: return None raise if sys.platform[:3] == "win": # winsock sometimes throws ENOTCONN - SOCKET_BLOCKING = set((errno.EWOULDBLOCK,)) + SOCKET_BLOCKING = set(EAGAIN_ALIASES) SOCKET_CLOSED = set((errno.ECONNRESET, errno.ENOTCONN, errno.ESHUTDOWN)) else: # oddly, on linux/darwin, an unconnected socket is expected to block, # so we treat ENOTCONN the same as EWOULDBLOCK - SOCKET_BLOCKING = set((errno.EWOULDBLOCK, errno.ENOTCONN)) + SOCKET_BLOCKING = set((errno.ENOTCONN,) + EAGAIN_ALIASES) SOCKET_CLOSED = set((errno.ECONNRESET, errno.ESHUTDOWN, errno.EPIPE)) @@ -368,7 +368,7 @@ class _SocketDuckForFd(object): data = os.read(self._fileno, buflen) return data except OSError as e: - if get_errno(e) != errno.EAGAIN: + if get_errno(e) not in EAGAIN_ALIASES: raise IOError(*e.args) trampoline(self, read=True) @@ -379,7 +379,7 @@ class _SocketDuckForFd(object): try: total_sent = os_write(fileno, data) except OSError as e: - if get_errno(e) != errno.EAGAIN: + if get_errno(e) not in EAGAIN_ALIASES: raise IOError(*e.args) total_sent = 0 while total_sent < len_data: @@ -387,7 +387,7 @@ class _SocketDuckForFd(object): try: total_sent += os_write(fileno, data[total_sent:]) except OSError as e: - if get_errno(e) != errno. EAGAIN: + if get_errno(e) not in EAGAIN_ALIASES: raise IOError(*e.args) def __del__(self): diff --git a/eventlet/support/__init__.py b/eventlet/support/__init__.py index c6d2c73..56344b3 100644 --- a/eventlet/support/__init__.py +++ b/eventlet/support/__init__.py @@ -1,8 +1,12 @@ +import errno import sys from eventlet.support import greenlets +EAGAIN_ALIASES = (errno.EAGAIN, errno.EWOULDBLOCK) + + def get_errno(exc): """ Get the error code out of socket.error objects. socket.error in <2.5 does not have errno attribute @@ -14,7 +18,8 @@ def get_errno(exc): """ try: - if exc.errno is not None: return exc.errno + if exc.errno is not None: + return exc.errno except AttributeError: pass try: |
