Fixed invalid argument bug. It turned out that spawning was relying on wsgi.server to not close the server socket, even though the code clearly intended to, at least for ssl sockets. It was an accident that it worked in the past, and when I corrected the case where the socket wasn't shutdown, spawning started breaking. It seems reasonable that the socket should remain open, so that's promoted to a tested feature.

This commit is contained in:
Ryan Williams
2010-01-11 18:59:45 -08:00
parent 8e27d09a32
commit a39bd8dbb4
3 changed files with 43 additions and 3 deletions

View File

@@ -23,9 +23,10 @@ Linden Lab Contributors
Thanks To
---------
* AdamKG, giving the hint that invalid argument errors were introduced post-0.9.0
* 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
* R. Tyler Ballance, bug report on tpool on Windows, reporting errors found in production
* Sergey Shepelev, PEP 8 police :-)
* Luci Stanescu, for reporting twisted hub bug
* Marcus Cavanaugh, for test case code that has been incredibly useful in tracking down bugs

View File

@@ -410,7 +410,10 @@ def server(sock, site,
minimum_chunk_size=None):
""" Start up a wsgi server handling requests from the supplied server socket.
This function loops forever.
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.
"""
serv = Server(sock, sock.getsockname(),
@@ -450,7 +453,11 @@ 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 e[0] != errno.EPIPE:

View File

@@ -1,4 +1,5 @@
import cgi
import errno
import os
import socket
from tests import skipped, LimitedTestCase
@@ -431,6 +432,37 @@ class TestHttpd(LimitedTestCase):
'4\r\n hai\r\n0\r\n\r\n')
self.assert_('hello!' in fd.read())
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)
# 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)
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'))
if __name__ == '__main__':
main()