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: v3.0.0~228 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b71650ffed24cb793ecd00466a5ccadd2e33b521;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. --- diff --git a/tornado/iostream.py b/tornado/iostream.py index 34fa9ed37..7f6ba7cac 100644 --- a/tornado/iostream.py +++ b/tornado/iostream.py @@ -162,8 +162,14 @@ class BaseIOStream(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 875dddfca..1177adbfc 100644 --- a/tornado/test/iostream_test.py +++ b/tornado/test/iostream_test.py @@ -301,6 +301,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 diff --git a/website/sphinx/releases/next.rst b/website/sphinx/releases/next.rst index 391c90aeb..b5043b395 100644 --- a/website/sphinx/releases/next.rst +++ b/website/sphinx/releases/next.rst @@ -156,3 +156,6 @@ In progress response code the same as a 303. This is contrary to the HTTP spec but consistent with all browsers and other major HTTP clients (including `CurlAsyncHTTPClient`). +* Fixed a bug with `IOStream.read_until_close` with a ``streaming_callback``, + which would cause some data to be passed to the final callback instead + of the streaming callback.