From: Ben Darnell Date: Mon, 27 Sep 2010 19:46:20 +0000 (-0700) Subject: Close the IOStream when the remote connection is closed. X-Git-Tag: v1.2.0~118 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8300c7ff93227a8cb3ef93b8b2cf8931949beb1c;p=thirdparty%2Ftornado.git Close the IOStream when the remote connection is closed. This was a regression introduced by http://github.com/facebook/tornado/commit/f6f7f83719a48083f3e5ed999e19c0ec67de9b9b Closes #143. --- diff --git a/tornado/iostream.py b/tornado/iostream.py index 3e76af12f..361955487 100644 --- a/tornado/iostream.py +++ b/tornado/iostream.py @@ -214,6 +214,9 @@ class IOStream(object): return None else: raise + if not chunk: + self.close() + return None return chunk def _read_to_buffer(self): @@ -358,4 +361,7 @@ class SSLIOStream(IOStream): return None else: raise + if not chunk: + self.close() + return None return chunk diff --git a/tornado/test/web_test.py b/tornado/test/web_test.py index 7f4a975d0..181ffe5ac 100644 --- a/tornado/test/web_test.py +++ b/tornado/test/web_test.py @@ -1,8 +1,11 @@ +from tornado.iostream import IOStream from tornado.testing import LogTrapTestCase, AsyncHTTPTestCase -from tornado.web import RequestHandler, _O, authenticated, Application +from tornado.web import RequestHandler, _O, authenticated, Application, asynchronous import logging import re +import socket +import tornado.ioloop class CookieTestRequestHandler(RequestHandler): # stub out enough methods to make the secure_cookie functions work @@ -79,3 +82,38 @@ class AuthRedirectTest(AsyncHTTPTestCase, LogTrapTestCase): self.assertTrue(re.match( 'http://example.com/login\?next=http%3A%2F%2Flocalhost%3A[0-9]+%2Fabsolute', response.headers['Location']), response.headers['Location']) + + +class ConnectionCloseHandler(RequestHandler): + def initialize(self, test): + self.test = test + + @asynchronous + def get(self): + self.test.on_handler_waiting() + + def on_connection_close(self): + self.test.on_connection_close() + +class ConnectionCloseTest(AsyncHTTPTestCase, LogTrapTestCase): + def get_app(self): + return Application([('/', ConnectionCloseHandler, dict(test=self))]) + + def test_connection_close(self): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) + s.connect(("localhost", self.get_http_port())) + self.stream = IOStream(s, io_loop=self.io_loop) + self.stream.write("GET / HTTP/1.0\r\n\r\n") + self.wait() + + def on_handler_waiting(self): + logging.info('handler waiting') + self.stream.close() + + def on_connection_close(self): + logging.info('connection closed') + self.stop() + +if tornado.ioloop._poll is tornado.ioloop._Select: + # select-based ioloop does not detect closed connections promptly + del ConnectionCloseTest