From 8072243926ecc1890fc6098357047497f043a57a Mon Sep 17 00:00:00 2001 From: Tavis Rudd Date: Wed, 24 Feb 2010 19:49:21 -0800 Subject: [PATCH] fix implementation of connect_ex so it always returns the error code rather than raising --- eventlet/greenio.py | 93 ++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 47 deletions(-) diff --git a/eventlet/greenio.py b/eventlet/greenio.py index da26dc6..cbbfa72 100644 --- a/eventlet/greenio.py +++ b/eventlet/greenio.py @@ -36,8 +36,8 @@ def socket_connect(descriptor, address): def socket_accept(descriptor): """ - Attempts to accept() on the descriptor, returns a client,address tuple - if it succeeds; returns None if it needs to trampoline, and raises + Attempts to accept() on the descriptor, returns a client,address tuple + if it succeeds; returns None if it needs to trampoline, and raises any exceptions. """ try: @@ -46,7 +46,7 @@ def socket_accept(descriptor): if e[0] == errno.EWOULDBLOCK: return None raise - + if sys.platform[:3]=="win": # winsock sometimes throws ENOTCONN @@ -62,7 +62,7 @@ else: def set_nonblocking(fd): """ Sets the descriptor to be nonblocking. Works on many file-like - objects as well as sockets. Only sockets can be nonblocking on + objects as well as sockets. Only sockets can be nonblocking on Windows, however. """ try: @@ -96,7 +96,7 @@ try: from socket import _GLOBAL_DEFAULT_TIMEOUT except ImportError: _GLOBAL_DEFAULT_TIMEOUT = object() - + class GreenSocket(object): """ @@ -117,14 +117,14 @@ class GreenSocket(object): self.timeout = fd.gettimeout() or socket.getdefaulttimeout() except AttributeError: self.timeout = socket.getdefaulttimeout() - + set_nonblocking(fd) self.fd = fd self.closed = False # when client calls setblocking(0) or settimeout(0) the socket must # act non-blocking self.act_non_blocking = False - + @property def _sock(self): return self @@ -195,11 +195,11 @@ class GreenSocket(object): else: end = time.time() + self.gettimeout() while True: - if socket_connect(fd, address): - return 0 - if time.time() >= end: - raise socket.timeout(errno.EAGAIN) try: + if socket_connect(fd, address): + return 0 + if time.time() >= end: + raise socket.timeout(errno.EAGAIN) trampoline(fd, write=True, timeout=end-time.time(), timeout_exc=socket.timeout(errno.EAGAIN)) except socket.error, ex: @@ -254,9 +254,9 @@ class GreenSocket(object): return '' else: raise - trampoline(fd, - read=True, - timeout=self.timeout, + trampoline(fd, + read=True, + timeout=self.timeout, timeout_exc=socket.timeout("timed out")) def recvfrom(self, *args): @@ -357,11 +357,11 @@ class GreenPipe(object): self.fd = fd self.closed = False self.recvbuffer = '' - + def close(self): self.fd.close() self.closed = True - + def fileno(self): return self.fd.fileno() @@ -419,7 +419,7 @@ class GreenPipe(object): def flush(self): pass - + def readuntil(self, terminator, size=None): buf, self.recvbuffer = self.recvbuffer, '' checked = 0 @@ -449,7 +449,7 @@ class GreenPipe(object): buf += d chunk, self.recvbuffer = buf[:size], buf[size:] return chunk - + def readline(self, size=None): return self.readuntil(self.newlines, size=size) @@ -484,24 +484,24 @@ except ImportError: class SSL(object): class WantWriteError(object): pass - + class WantReadError(object): pass - + class ZeroReturnError(object): pass - + class SysCallError(object): pass - + def shutdown_safe(sock): """ Shuts down the socket. This is a convenience method for - code that wants to gracefully handle regular sockets, SSL.Connection + code that wants to gracefully handle regular sockets, SSL.Connection sockets from PyOpenSSL and ssl.SSLSocket objects from Python 2.6 interchangeably. Both types of ssl socket require a shutdown() before close, but they have different arity on their shutdown method. - + Regular sockets don't need a shutdown before close, but it doesn't hurt. """ try: @@ -516,11 +516,11 @@ def shutdown_safe(sock): # this will often be the case in an http server context if e[0] != errno.ENOTCONN: raise - - + + def connect(addr, family=socket.AF_INET, bind=None): """Convenience function for opening client sockets. - + :param addr: Address of the server to connect to. For TCP sockets, this is a (host, port) tuple. :param family: Socket family, optional. See :mod:`socket` documentation for available families. :param bind: Local address to bind to, optional. @@ -531,14 +531,14 @@ def connect(addr, family=socket.AF_INET, bind=None): sock.bind(bind) sock.connect(addr) return sock - - + + def listen(addr, family=socket.AF_INET, backlog=50): """Convenience function for opening server sockets. This socket can be used in an ``accept()`` loop. Sets SO_REUSEADDR on the socket to save on annoyance. - + :param addr: Address to listen on. For TCP sockets, this is a (host, port) tuple. :param family: Socket family, optional. See :mod:`socket` documentation for available families. :param backlog: The maximum number of queued connections. Should be at least 1; the maximum value is system-dependent. @@ -552,41 +552,40 @@ def listen(addr, family=socket.AF_INET, backlog=50): def wrap_ssl(sock, keyfile=None, certfile=None, server_side=False, - cert_reqs=None, ssl_version=None, ca_certs=None, + cert_reqs=None, ssl_version=None, ca_certs=None, do_handshake_on_connect=True, suppress_ragged_eofs=True): - """Convenience function for converting a regular socket into an SSL - socket. Has the same interface as :func:`ssl.wrap_socket`, but + """Convenience function for converting a regular socket into an SSL + socket. Has the same interface as :func:`ssl.wrap_socket`, but works on 2.5 or earlier, using PyOpenSSL. The preferred idiom is to call wrap_ssl directly on the creation - method, e.g., ``wrap_ssl(connect(addr))`` or + method, e.g., ``wrap_ssl(connect(addr))`` or ``wrap_ssl(listen(addr), server_side=True)``. This way there is no "naked" socket sitting around to accidentally corrupt the SSL session. - + :return Green SSL object. """ pass def serve(sock, handle, concurrency=1000): - """Runs a server on the supplied socket. Calls the function - *handle* in a separate greenthread for every incoming request. - This function blocks the calling greenthread; it won't return until + """Runs a server on the supplied socket. Calls the function + *handle* in a separate greenthread for every incoming request. + This function blocks the calling greenthread; it won't return until the server completes. If you desire an immediate return, spawn a new greenthread for :func:`serve`. - - The *handle* function must raise an EndServerException to - gracefully terminate the server -- that's the only way to get the + + The *handle* function must raise an EndServerException to + gracefully terminate the server -- that's the only way to get the server() function to return. Any other uncaught exceptions raised - in *handle* are raised as exceptions from :func:`serve`, so be - sure to do a good job catching exceptions that your application + in *handle* are raised as exceptions from :func:`serve`, so be + sure to do a good job catching exceptions that your application raises. The return value of *handle* is ignored. - The value in *concurrency* controls the maximum number of - greenthreads that will be open at any time handling requests. When - the server hits the concurrency limit, it stops accepting new + The value in *concurrency* controls the maximum number of + greenthreads that will be open at any time handling requests. When + the server hits the concurrency limit, it stops accepting new connections until the existing ones complete. """ pass -