]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Check for EOF in the kqueue-based IOLoop to avoid incorrectly calling
authorBen Darnell <ben@bendarnell.com>
Tue, 22 Feb 2011 21:35:41 +0000 (13:35 -0800)
committerBen Darnell <ben@bendarnell.com>
Tue, 22 Feb 2011 21:35:41 +0000 (13:35 -0800)
the connect callback when the connection was refused.

Closes #223.

tornado/ioloop.py
tornado/test/iostream_test.py

index a7445d7cda455ea4d2fb05f14904297264de635b..62b2b0900b042de9b1a0eddee4be9a721a53bdd6 100644 (file)
@@ -490,7 +490,17 @@ class _KQueue(object):
             if kevent.filter == select.KQ_FILTER_READ:
                 events[fd] = events.get(fd, 0) | IOLoop.READ
             if kevent.filter == select.KQ_FILTER_WRITE:
-                events[fd] = events.get(fd, 0) | IOLoop.WRITE
+                if kevent.flags & select.KQ_EV_EOF:
+                    # If an asynchronous connection is refused, kqueue
+                    # returns a write event with the EOF flag set.
+                    # Turn this into an error for consistency with the
+                    # other IOLoop implementations.
+                    # Note that for read events, EOF may be returned before
+                    # all data has been consumed from the socket buffer,
+                    # so we only check for EOF on write events.
+                    events[fd] = IOLoop.ERROR
+                else:
+                    events[fd] = events.get(fd, 0) | IOLoop.WRITE
             if kevent.flags & select.KQ_EV_ERROR:
                 events[fd] = events.get(fd, 0) | IOLoop.ERROR
         return events.items()
index 8e0d64f5cc2ca7e7cf8c3bbd5242789cbe9c1c85..48ccd4a6c3b6799487b5469598fcc69232a35bc1 100644 (file)
@@ -1,5 +1,5 @@
 from tornado.iostream import IOStream
-from tornado.testing import AsyncHTTPTestCase, LogTrapTestCase
+from tornado.testing import AsyncHTTPTestCase, LogTrapTestCase, get_unused_port
 from tornado.web import RequestHandler, Application
 import socket
 
@@ -31,3 +31,18 @@ class TestIOStream(AsyncHTTPTestCase, LogTrapTestCase):
         self.stream.read_bytes(3, self.stop)
         data = self.wait()
         self.assertEqual(data, "200")
+
+    def test_connection_refused(self):
+        # When a connection is refused, the connect callback should not
+        # be run.  (The kqueue IOLoop used to behave differently from the
+        # epoll IOLoop in this respect)
+        port = get_unused_port()
+        stream = IOStream(socket.socket(), self.io_loop)
+        self.connect_called = False
+        def connect_callback():
+            self.connect_called = True
+        stream.set_close_callback(self.stop)
+        stream.connect(("localhost", port), connect_callback)
+        self.wait()
+        self.assertFalse(self.connect_called)
+