Merge
This commit is contained in:
3
AUTHORS
3
AUTHORS
@@ -23,13 +23,14 @@ Linden Lab Contributors
|
||||
|
||||
Thanks To
|
||||
---------
|
||||
* AdamKG, giving the hint that invalid argument errors were introduced post-0.9.0
|
||||
* Michael Barton, 100-continue patch, content-length bugfixes for wsgi
|
||||
* gholt, wsgi patches for accepting a custom pool, and returning 400 if content-length is invalid
|
||||
* Luke Tucker, bug report regarding wsgi + webob
|
||||
* Chuck Thier, reporting a bug in processes.py
|
||||
* Brantley Harris, reporting bug #4
|
||||
* Taso Du Val, reproing an exception squelching bug, saving children's lives ;-)
|
||||
* R. Tyler Ballance, bug report on tpool on Windows, help with improving corolocal module, profile performance report, suggestion use flush that fixed tpool on Windows
|
||||
* R. Tyler Ballance, bug report on tpool on Windows, help with improving corolocal module, profile performance report, suggestion use flush that fixed tpool on Windows, reporting a bug in wsgi the day after it was introduced, reporting errors found in production use of spawning
|
||||
* Sergey Shepelev, PEP 8 police :-), reporting bug #5
|
||||
* Luci Stanescu, for reporting twisted hub bug
|
||||
* Marcus Cavanaugh, for test case code that has been incredibly useful in tracking down bugs
|
||||
|
@@ -162,7 +162,7 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
except greenio.SSL.ZeroReturnError:
|
||||
self.raw_requestline = ''
|
||||
except socket.error, e:
|
||||
if getattr(e, 'errno', 0) not in BAD_SOCK:
|
||||
if e[0] not in BAD_SOCK:
|
||||
raise
|
||||
self.raw_requestline = ''
|
||||
|
||||
@@ -192,7 +192,7 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
self.handle_one_response()
|
||||
except socket.error, e:
|
||||
# Broken pipe, connection reset by peer
|
||||
if getattr(e, 'errno', 0) not in BROKEN_SOCK:
|
||||
if e[0] not in BROKEN_SOCK:
|
||||
raise
|
||||
finally:
|
||||
self.server.outstanding_requests -= 1
|
||||
@@ -433,6 +433,7 @@ class Server(BaseHTTPServer.HTTPServer):
|
||||
def log_message(self, message):
|
||||
self.log.write(message + '\n')
|
||||
|
||||
ACCEPT_SOCK = set((errno.EPIPE, errno.EBADF))
|
||||
|
||||
def server(sock, site,
|
||||
log=None,
|
||||
@@ -446,7 +447,9 @@ def server(sock, site,
|
||||
custom_pool=None,
|
||||
log_format=DEFAULT_LOG_FORMAT):
|
||||
""" Start up a wsgi server handling requests from the supplied server
|
||||
socket. This function loops forever.
|
||||
socket. This function loops forever. The *sock* object will be closed after server exits,
|
||||
but the underlying file descriptor will remain open, so if you have a dup() of *sock*,
|
||||
it will remain usable.
|
||||
|
||||
:param sock: Server socket, must be already bound to a port and listening.
|
||||
:param site: WSGI application function.
|
||||
@@ -495,7 +498,7 @@ def server(sock, site,
|
||||
try:
|
||||
client_socket = sock.accept()
|
||||
except socket.error, e:
|
||||
if getattr(e, 'errno', 0) not in BAD_SOCK + BROKEN_SOCK:
|
||||
if e[0] not in ACCEPT_SOCK:
|
||||
raise
|
||||
pool.execute_async(serv.process_request, client_socket)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
@@ -503,9 +506,13 @@ def server(sock, site,
|
||||
break
|
||||
finally:
|
||||
try:
|
||||
greenio.shutdown_safe(sock)
|
||||
# NOTE: It's not clear whether we want this to leave the
|
||||
# socket open or close it. Use cases like Spawning want
|
||||
# the underlying fd to remain open, but if we're going
|
||||
# that far we might as well not bother closing sock at
|
||||
# all.
|
||||
sock.close()
|
||||
except socket.error, e:
|
||||
if getattr(e, 'errno', 0) not in BROKEN_SOCK:
|
||||
if e[0] not in BROKEN_SOCK:
|
||||
traceback.print_exc()
|
||||
|
||||
|
@@ -1,12 +1,15 @@
|
||||
import cgi
|
||||
import errno
|
||||
import os
|
||||
import socket
|
||||
import sys
|
||||
from tests import skipped, LimitedTestCase
|
||||
from unittest import main
|
||||
|
||||
from eventlet import api
|
||||
from eventlet import util
|
||||
from eventlet import greenio
|
||||
from eventlet.green import socket as greensocket
|
||||
from eventlet import wsgi
|
||||
from eventlet import processes
|
||||
|
||||
@@ -529,7 +532,41 @@ class TestHttpd(LimitedTestCase):
|
||||
self.assert_('1.2.3.4' not in self.logfile.getvalue())
|
||||
self.assert_('5.6.7.8' not in self.logfile.getvalue())
|
||||
self.assert_('127.0.0.1' in self.logfile.getvalue())
|
||||
|
||||
|
||||
def test_socket_remains_open(self):
|
||||
api.kill(self.killer)
|
||||
server_sock = api.tcp_listener(('localhost', 0))
|
||||
self.port = server_sock.getsockname()[1]
|
||||
server_sock_2 = server_sock.dup()
|
||||
self.killer = api.spawn(wsgi.server, server_sock_2, hello_world,
|
||||
log=self.logfile)
|
||||
# do a single req/response to verify it's up
|
||||
sock = api.connect_tcp(('localhost', self.port))
|
||||
fd = sock.makeGreenFile()
|
||||
fd.write('GET / HTTP/1.0\r\nHost: localhost\r\n\r\n')
|
||||
result = fd.read()
|
||||
fd.close()
|
||||
self.assert_(result.startswith('HTTP'), result)
|
||||
self.assert_(result.endswith('hello world'))
|
||||
|
||||
# shut down the server and verify the server_socket fd is still open,
|
||||
# but the actual socketobject passed in to wsgi.server is closed
|
||||
api.kill(self.killer)
|
||||
api.sleep(0.01)
|
||||
try:
|
||||
server_sock_2.accept()
|
||||
except socket.error, exc:
|
||||
self.assertEqual(exc[0], errno.EBADF)
|
||||
self.killer = api.spawn(wsgi.server, server_sock, hello_world,
|
||||
log=self.logfile)
|
||||
sock = api.connect_tcp(('localhost', self.port))
|
||||
fd = sock.makeGreenFile()
|
||||
fd.write('GET / HTTP/1.0\r\nHost: localhost\r\n\r\n')
|
||||
result = fd.read()
|
||||
fd.close()
|
||||
self.assert_(result.startswith('HTTP'), result)
|
||||
self.assert_(result.endswith('hello world'))
|
||||
|
||||
def test_021_environ_clobbering(self):
|
||||
def clobberin_time(environ, start_response):
|
||||
for environ_var in ['wsgi.version', 'wsgi.url_scheme',
|
||||
@@ -620,7 +657,34 @@ class TestHttpd(LimitedTestCase):
|
||||
self.assertEquals(fd.read(7), 'testing')
|
||||
fd.close()
|
||||
|
||||
def test_025_log_format(self):
|
||||
def test_025_accept_errors(self):
|
||||
api.kill(self.killer)
|
||||
listener = greensocket.socket()
|
||||
listener.bind(('localhost', 0))
|
||||
# NOT calling listen, to trigger the error
|
||||
self.port = listener.getsockname()[1]
|
||||
self.killer = api.spawn(
|
||||
wsgi.server,
|
||||
listener,
|
||||
self.site,
|
||||
max_size=128,
|
||||
log=self.logfile)
|
||||
old_stderr = sys.stderr
|
||||
try:
|
||||
sys.stderr = self.logfile
|
||||
api.sleep(0) # need to enter server loop
|
||||
try:
|
||||
api.connect_tcp(('localhost', self.port))
|
||||
self.fail("Didn't expect to connect")
|
||||
except socket.error, exc:
|
||||
self.assertEquals(exc[0], errno.ECONNREFUSED)
|
||||
|
||||
self.assert_('Invalid argument' in self.logfile.getvalue(),
|
||||
self.logfile.getvalue())
|
||||
finally:
|
||||
sys.stderr = old_stderr
|
||||
|
||||
def test_026_log_format(self):
|
||||
self.spawn_server(log_format="HI %(request_line)s HI")
|
||||
sock = api.connect_tcp(('localhost', self.port))
|
||||
sock.sendall('GET /yo! HTTP/1.1\r\nHost: localhost\r\n\r\n')
|
||||
|
Reference in New Issue
Block a user