From: Ben Darnell Date: Fri, 9 Nov 2012 04:29:45 +0000 (-0500) Subject: Fix a bug with IOStream.read_until_close with a streaming_callback. X-Git-Tag: v2.4.1~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=722731d571a72e7f0a84ac731287d8540a340096;p=thirdparty%2Ftornado.git Fix a bug with IOStream.read_until_close with a streaming_callback. If the underlying socket was already closed the buffered data would be passed to the final callback rather than the streaming callback. Conflicts: website/sphinx/releases/next.rst --- diff --git a/tornado/iostream.py b/tornado/iostream.py index 25caf3ee6..e7bcf654a 100644 --- a/tornado/iostream.py +++ b/tornado/iostream.py @@ -176,8 +176,14 @@ class IOStream(object): a ``streaming_callback`` is not used. """ self._set_read_callback(callback) + self._streaming_callback = stack_context.wrap(streaming_callback) if self.closed(): - self._run_callback(callback, self._consume(self._read_buffer_size)) + if self._streaming_callback is not None: + self._run_callback(self._streaming_callback, + self._consume(self._read_buffer_size)) + self._run_callback(self._read_callback, + self._consume(self._read_buffer_size)) + self._streaming_callback = None self._read_callback = None return self._read_until_close = True diff --git a/tornado/test/iostream_test.py b/tornado/test/iostream_test.py index 3b051d34e..a36343435 100644 --- a/tornado/test/iostream_test.py +++ b/tornado/test/iostream_test.py @@ -296,6 +296,42 @@ class TestIOStreamMixin(object): server.close() client.close() + def test_read_until_close_after_close(self): + # Similar to test_delayed_close_callback, but read_until_close takes + # a separate code path so test it separately. + server, client = self.make_iostream_pair() + client.set_close_callback(self.stop) + try: + server.write(b("1234")) + server.close() + self.wait() + client.read_until_close(self.stop) + data = self.wait() + self.assertEqual(data, b("1234")) + finally: + server.close() + client.close() + + def test_streaming_read_until_close_after_close(self): + # Same as the preceding test but with a streaming_callback. + # All data should go through the streaming callback, + # and the final read callback just gets an empty string. + server, client = self.make_iostream_pair() + client.set_close_callback(self.stop) + try: + server.write(b("1234")) + server.close() + self.wait() + streaming_data = [] + client.read_until_close(self.stop, + streaming_callback=streaming_data.append) + data = self.wait() + self.assertEqual(b(''), data) + self.assertEqual(b('').join(streaming_data), b("1234")) + finally: + server.close() + client.close() + def test_large_read_until(self): # Performance test: read_until used to have a quadratic component # so a read_until of 4MB would take 8 seconds; now it takes 0.25