From d0040bf5c695a504fc7817ed7e2b4e96882a98d1 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Thu, 11 Feb 2010 00:09:54 -0800 Subject: [PATCH] Fixed bug exposed by redbo's unit test, tweaked test itself a bit based on experimentation. --- eventlet/wsgi.py | 20 +++++++++++++------- tests/wsgi_test.py | 25 +++++++++++++++++++------ 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/eventlet/wsgi.py b/eventlet/wsgi.py index fd481f7..4bd7345 100644 --- a/eventlet/wsgi.py +++ b/eventlet/wsgi.py @@ -471,7 +471,14 @@ class Server(BaseHTTPServer.HTTPServer): def log_message(self, message): self.log.write(message + '\n') -ACCEPT_SOCK = set((errno.EPIPE, errno.EBADF)) +try: + import ssl + ACCEPT_EXCEPTIONS = (socket.error, ssl.SSLError) + ACCEPT_ERRNO = set((errno.EPIPE, errno.EBADF, + ssl.SSL_ERROR_EOF, ssl.SSL_ERROR_SSL)) +except ImportError: + ACCEPT_EXCEPTIONS = (socket.error,) + ACCEPT_ERRNO = set((errno.EPIPE, errno.EBADF)) def server(sock, site, log=None, @@ -536,19 +543,18 @@ def server(sock, site, serv.log.write("(%s) wsgi starting up on %s://%s%s/\n" % (os.getpid(), scheme, host, port)) while True: try: + client_socket = sock.accept() try: - client_socket = sock.accept() - except socket.error, e: - if get_errno(e) not in ACCEPT_SOCK: - raise - try: - pool.spawn_n(serv.process_request, client_socket) + pool.spawn_n(serv.process_request, client_socket) except AttributeError: warnings.warn("wsgi's pool should be an instance of " \ "eventlet.greenpool.GreenPool, is %s. Please convert your"\ " call site to use GreenPool instead" % type(pool), DeprecationWarning, stacklevel=2) pool.execute_async(serv.process_request, client_socket) + except ACCEPT_EXCEPTIONS, e: + if get_errno(e) not in ACCEPT_ERRNO: + raise except (KeyboardInterrupt, SystemExit): serv.log.write("wsgi exiting\n") break diff --git a/tests/wsgi_test.py b/tests/wsgi_test.py index 5c87e32..b8a48e5 100644 --- a/tests/wsgi_test.py +++ b/tests/wsgi_test.py @@ -741,19 +741,32 @@ class TestHttpd(LimitedTestCase): try: wsgi.server(sock=sock, site=hello_world, log=self.logfile) errored[0] = 'SSL handshake error caused wsgi.server to exit.' + except greenthread.greenlet.GreenletExit: + pass except Exception, e: errored[0] = 'SSL handshake error raised exception %s.' % e - srv_sock = api.ssl_listener(('localhost', 0), certificate_file, private_key_file) - port = srv_sock.getsockname()[1] for data in ('', 'GET /non-ssl-request HTTP/1.0\r\n\r\n'): - g = eventlet.spawn(server, srv_sock) - sock = api.connect_tcp(('localhost', port)) + srv_sock = api.ssl_listener(('localhost', 0), certificate_file, private_key_file) + port = srv_sock.getsockname()[1] + g = eventlet.spawn_n(server, srv_sock) + client = api.connect_tcp(('localhost', port)) if data: # send non-ssl request - sock.sendall(data) + client.sendall(data) else: # close sock prematurely - sock.close() + client.close() api.sleep(0) # let context switch back to server self.assert_(not errored[0], errored[0]) + # make another request to ensure the server's still alive + try: + from eventlet.green import ssl + client = ssl.wrap_socket(api.connect_tcp(('localhost', port))) + client.write('GET / HTTP/1.0\r\nHost: localhost\r\n\r\n') + result = client.read() + self.assert_(result.startswith('HTTP'), result) + self.assert_(result.endswith('hello world')) + except ImportError: + pass # TODO: should test with OpenSSL + greenthread.kill(g) if __name__ == '__main__': main()