import os import select import socket import errno def g_log(*args): import sys from eventlet.support import greenlets as greenlet g_id = id(greenlet.getcurrent()) if g_id is None: if greenlet.getcurrent().parent is None: ident = 'greenlet-main' else: g_id = id(greenlet.getcurrent()) if g_id < 0: g_id += 1 + ((sys.maxint + 1) << 1) ident = '%08X' % (g_id,) else: ident = 'greenlet-%d' % (g_id,) print >>sys.stderr, '[%s] %s' % (ident, ' '.join(map(str, args))) __original_socket__ = socket.socket __original_gethostbyname__ = socket.gethostbyname __original_getaddrinfo__ = socket.getaddrinfo try: __original_fromfd__ = socket.fromfd __original_fork__ = os.fork except AttributeError: # Windows __original_fromfd__ = None __original_fork__ = None def tcp_socket(): s = __original_socket__(socket.AF_INET, socket.SOCK_STREAM) return s try: try: import ssl __original_ssl__ = ssl.wrap_socket except ImportError: __original_ssl__ = socket.ssl except AttributeError: __original_ssl__ = None def wrap_ssl(sock, certificate=None, private_key=None): from OpenSSL import SSL from eventlet import greenio context = SSL.Context(SSL.SSLv23_METHOD) if certificate is not None: context.use_certificate_file(certificate) if private_key is not None: context.use_privatekey_file(private_key) context.set_verify(SSL.VERIFY_NONE, lambda *x: True) ## TODO only do this on client sockets? how? connection = SSL.Connection(context, sock) connection.set_connect_state() return greenio.GreenSSL(connection) def wrap_ssl_obj(sock, certificate=None, private_key=None): """ For 100% compatibility with the socket module, this wraps and handshakes an open connection, returning a SSLObject.""" from eventlet import greenio wrapped = wrap_ssl(sock, certificate, private_key) return greenio.GreenSSLObject(wrapped) socket_already_wrapped = False def wrap_socket_with_coroutine_socket(use_thread_pool=True): global socket_already_wrapped if socket_already_wrapped: return def new_socket(*args, **kw): from eventlet import greenio return greenio.GreenSocket(__original_socket__(*args, **kw)) socket.socket = new_socket # for 100% compatibility, return a GreenSSLObject socket.ssl = wrap_ssl_obj if use_thread_pool: try: from eventlet import tpool def new_gethostbyname(*args, **kw): return tpool.execute( __original_gethostbyname__, *args, **kw) socket.gethostbyname = new_gethostbyname def new_getaddrinfo(*args, **kw): return tpool.execute( __original_getaddrinfo__, *args, **kw) socket.getaddrinfo = new_getaddrinfo except ImportError: pass # Windows if __original_fromfd__ is not None: def new_fromfd(*args, **kw): from eventlet import greenio return greenio.GreenSocket(__original_fromfd__(*args, **kw)) socket.fromfd = new_fromfd socket_already_wrapped = True __original_fdopen__ = os.fdopen __original_read__ = os.read __original_write__ = os.write __original_waitpid__ = os.waitpid ## TODO wrappings for popen functions? not really needed since Process object exists? pipes_already_wrapped = False def wrap_pipes_with_coroutine_pipes(): from eventlet import processes ## Make sure the signal handler is installed global pipes_already_wrapped if pipes_already_wrapped: return def new_fdopen(*args, **kw): from eventlet import greenio return greenio.GreenPipe(__original_fdopen__(*args, **kw)) def new_read(fd, *args, **kw): from eventlet import api try: api.trampoline(fd, read=True) except socket.error, e: if e[0] == errno.EPIPE: return '' else: raise return __original_read__(fd, *args, **kw) def new_write(fd, *args, **kw): from eventlet import api api.trampoline(fd, write=True) return __original_write__(fd, *args, **kw) def new_fork(*args, **kwargs): pid = __original_fork__() if pid: processes._add_child_pid(pid) return pid def new_waitpid(pid, options): from eventlet import processes evt = processes.CHILD_EVENTS.get(pid) if not evt: return 0, 0 if options == os.WNOHANG: if evt.ready(): return pid, evt.wait() return 0, 0 elif options: return __original_waitpid__(pid, options) return pid, evt.wait() os.fdopen = new_fdopen os.read = new_read os.write = new_write if __original_fork__ is not None: os.fork = new_fork os.waitpid = new_waitpid __original_select__ = select.select def fake_select(r, w, e, timeout): """ This is to cooperate with people who are trying to do blocking reads with a *timeout*. This only works if *r*, *w*, and *e* aren't bigger than len 1, and if either *r* or *w* is populated. Install this with :func:`wrap_select_with_coroutine_select`, which makes the global ``select.select`` into :func:`fake_select`. """ from eventlet import api assert len(r) <= 1 assert len(w) <= 1 assert len(e) <= 1 if w and r: raise RuntimeError('fake_select doesn\'t know how to do that yet') try: if r: api.trampoline(r[0], read=True, timeout=timeout) return r, [], [] else: api.trampoline(w[0], write=True, timeout=timeout) return [], w, [] except api.TimeoutError, e: return [], [], [] except: return [], [], e def wrap_select_with_coroutine_select(): select.select = fake_select try: import threading __original_threadlocal__ = threading.local except ImportError: pass def wrap_threading_local_with_coro_local(): """ monkey patch ``threading.local`` with something that is greenlet aware. Since greenlets cannot cross threads, so this should be semantically identical to ``threadlocal.local`` """ from eventlet import api def get_ident(): return id(api.getcurrent()) class local(object): def __init__(self): self.__dict__['__objs'] = {} def __getattr__(self, attr, g=get_ident): try: return self.__dict__['__objs'][g()][attr] except KeyError: raise AttributeError( "No variable %s defined for the thread %s" % (attr, g())) def __setattr__(self, attr, value, g=get_ident): self.__dict__['__objs'].setdefault(g(), {})[attr] = value def __delattr__(self, attr, g=get_ident): try: del self.__dict__['__objs'][g()][attr] except KeyError: raise AttributeError( "No variable %s defined for thread %s" % (attr, g())) threading.local = local def socket_bind_and_listen(descriptor, addr=('', 0), backlog=50): set_reuse_addr(descriptor) descriptor.bind(addr) descriptor.listen(backlog) return descriptor def set_reuse_addr(descriptor): try: descriptor.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, descriptor.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR) | 1, ) except socket.error: pass