From 001936a6f250b02bf25881d9fd48e294fc45b38a Mon Sep 17 00:00:00 2001 From: donovan Date: Thu, 8 May 2008 09:17:08 -0700 Subject: [PATCH] Update the nginx mod_wsgi support to the latest mod_wsgi semantics; there's a bug that's currently preventing it from working, though. --- eventlet/hubs/nginx.py | 147 ++++++++++++++++++++++++++--- eventlet/support/nginx_mod_wsgi.py | 67 ------------- 2 files changed, 133 insertions(+), 81 deletions(-) delete mode 100644 eventlet/support/nginx_mod_wsgi.py diff --git a/eventlet/hubs/nginx.py b/eventlet/hubs/nginx.py index b23dc04..b25ab39 100644 --- a/eventlet/hubs/nginx.py +++ b/eventlet/hubs/nginx.py @@ -23,31 +23,150 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ + + +from os.path import abspath, dirname +import sys +import traceback + +sys.stdout = sys.stderr +mydir = dirname(dirname(dirname(abspath(__file__)))) +if mydir not in sys.path: + sys.path.append(mydir) + + +from eventlet import api from eventlet import greenlib +from eventlet import httpc from eventlet.hubs import hub +from eventlet import util + + +util.wrap_socket_with_coroutine_socket() + + +def hello_world(env, start_response): + result = httpc.get('http://www.google.com/') + start_response('200 OK', [('Content-type', 'text/plain')]) + return [result] + + +def wrap_application(master, env, start_response): + try: + real_application = api.named(env['eventlet_nginx_wsgi_app']) + except: + real_application = hello_world + result = real_application(env, start_response) + master.switch((result, None)) + return None, None + + +class StartResponse(object): + def __call__(self, *args): + self.args = args + + +pythonpath_already_set = False + + WSGI_POLLIN = 0x01 WSGI_POLLOUT = 0x04 - +import traceback class Hub(hub.BaseHub): - def add_descriptor(self, fileno, read=None, write=None, exc=None): - super(Hub, self).add_descriptor(fileno, read, write, exc) + def __init__(self, *args, **kw): + hub.BaseHub.__init__(self, *args, **kw) + self._connection_wrappers = {} + + def add_descriptor(self, fileno, read=None, write=None, exc=None): + print "ADD DESCRIPTOR", fileno, read, write, exc + traceback.print_stack() + + super(Hub, self).add_descriptor(fileno, read, write, exc) + flag = 0 + if read: + flag |= WSGI_POLLIN + if write: + flag |= WSGI_POLLOUT + conn = self.connection_wrapper(fileno) + self._connection_wrappers[fileno] = conn + print "POLL REGISTER", flag + self.poll_register(conn, flag) - if read is not None: - self.poll_register(fileno, WSGI_POLLIN) - elif write is not None: - self.poll_register(fileno, WSGI_POLLOUT) - def remove_descriptor(self, fileno): super(Hub, self).remove_descriptor(fileno) - self.poll_unregister(fileno) - - def wait(self, seconds=None): - if seconds is not None: - self.sleep(int(seconds*1000)) + try: + self.poll_unregister(self._connection_wrappers[fileno]) + except RuntimeError: + pass - greenlib.switch(self.current_application) + def wait(self, seconds=0): + to_call = getattr(self, 'to_call', None) + print "WAIT", self, to_call + if to_call: + print "CALL TOCALL" + result = to_call[0](to_call[1]) + del self.to_call + return result + greenlib.switch(self.current_application, self.poll(int(seconds*1000))) + + def application(self, env, start_response): + print "ENV",env + self.poll_register = env['ngx.poll_register'] + self.poll_unregister = env['ngx.poll_unregister'] + self.poll = env['ngx.poll'] + self.connection_wrapper = env['ngx.connection_wrapper'] + self.current_application = api.getcurrent() + + slave = api.greenlet.greenlet(wrap_application) + response = StartResponse() + result = slave.switch( + api.getcurrent(), env, response) + + while True: + self.current_application = api.getcurrent() + print "RESULT", result, callable(result[0]) + if result and callable(result[0]): + print "YIELDING!" + yield '' + print "AFTER YIELD!" + conn, flags = result[0]() + fileno = conn.fileno() + if flags & WSGI_POLLIN: + self.readers[fileno](fileno) + elif flags & WSGI_POLLOUT: + self.writers[fileno](fileno) + print "POLL STATE", conn, flags, dir(conn) + else: + start_response(*response.args) + if isinstance(result, tuple): + for x in result[0]: + yield x + else: + for x in result: + yield x + return + result = self.switch() + if not isinstance(result, tuple): + result = (result, None) ## TODO Fix greenlib's return values + + +def application(env, start_response): + hub = api.get_hub() + + if not isinstance(hub, Hub): + api.use_hub(sys.modules[Hub.__module__]) + hub = api.get_hub() + + global pythonpath_already_set + if not pythonpath_already_set: + pythonpath = env.get('eventlet_python_path', '').split(':') + for seg in pythonpath: + if seg not in sys.path: + sys.path.append(seg) + + return hub.application(env, start_response) diff --git a/eventlet/support/nginx_mod_wsgi.py b/eventlet/support/nginx_mod_wsgi.py deleted file mode 100644 index 1035680..0000000 --- a/eventlet/support/nginx_mod_wsgi.py +++ /dev/null @@ -1,67 +0,0 @@ - -import sys -import traceback - -sys.path.insert(0, '/Users/donovan/Code/mulib-hg') -sys.stdout = sys.stderr - -from eventlet import api -from eventlet import httpc - -from eventlet.hubs import nginx - - -def old_real_application(env, start_response): - #result = httpc.get('http://127.0.0.1:8081/') - start_response('200 OK', [('Content-type', 'text/plain')]) - #sys.stderr.write("RESULT %r" % (result, )) - return 'hello' - - -def wrap_application(master, env, start_response): - real_application = api.named(env['eventlet_nginx_wsgi_app']) - result = real_application(env, start_response) - ## Should catch exception and return here? - #sys.stderr.write("RESULT2 %r" % (result, )) - master.switch((result, None)) - return None, None - - -class StartResponse(object): - def __init__(self, start_response): - self.start_response = start_response - - def __call__(self, *args): - self.args = args - - -def application(env, start_response): - hub = api.get_hub() - - if not isinstance(hub, nginx.Hub): - api.use_hub(nginx) - - hub.poll_register = env['ngx.poll_register'] - hub.poll_unregister = env['ngx.poll_unregister'] - hub.sleep = env['ngx.sleep'] - hub.current_application = api.getcurrent() - - slave = api.greenlet.greenlet(wrap_application) - response = StartResponse(start_response) - result = slave.switch( - hub.current_application, env, response) - - while True: - #sys.stderr.write("RESULT3 %r" % (result, )) - if result is None or result == (None, None): - yield '' - else: - start_response(*response.args) - if isinstance(result, tuple): - for x in result[0]: - yield x - else: - for x in result: - yield x - return - result = hub.switch()