summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rw-r--r--eventlet/green/os.py25
-rw-r--r--eventlet/green/ssl.py11
-rw-r--r--eventlet/greenio.py16
-rw-r--r--eventlet/support/__init__.py7
5 files changed, 37 insertions, 23 deletions
diff --git a/AUTHORS b/AUTHORS
index 1f6a71e..e8c890c 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -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: