]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Make tornado.netutil.add_accept_handler pass a fileobj to the IOLoop.
authorBen Darnell <ben@bendarnell.com>
Sat, 18 Jan 2014 21:42:06 +0000 (16:42 -0500)
committerBen Darnell <ben@bendarnell.com>
Sat, 18 Jan 2014 21:42:06 +0000 (16:42 -0500)
Officially allow mixing of fds and file objects so that callers of
add_accept_handler don't need to know about this change.

As a side effect, fixes a problem with autoreload on windows.

Closes #737.

tornado/netutil.py
tornado/platform/asyncio.py
tornado/test/ioloop_test.py

index 8ebe604d2f98e526b84baf5b5917ec5c9e5a310f..7c89dc511fd5ddea4815e020264993d5396e4f9d 100644 (file)
@@ -165,7 +165,7 @@ def add_accept_handler(sock, callback, io_loop=None):
                     continue
                 raise
             callback(connection, address)
-    io_loop.add_handler(sock.fileno(), accept_handler, IOLoop.READ)
+    io_loop.add_handler(sock, accept_handler, IOLoop.READ)
 
 
 def is_valid_ip(ip):
index b6755e483516d1092ac89fc452b00211e3bb400a..9b70cd4fb0778885ac2b19d7d1441b6e64a53fb8 100644 (file)
@@ -24,7 +24,7 @@ class BaseAsyncIOLoop(IOLoop):
         self.asyncio_loop = asyncio_loop
         self.close_loop = close_loop
         self.asyncio_loop.call_soon(self.make_current)
-        # Maps fd to handler function (as in IOLoop.add_handler)
+        # Maps fd to (fileobj, handler function) pair (as in IOLoop.add_handler)
         self.handlers = {}
         # Set of fds listening for reads/writes
         self.readers = set()
@@ -34,16 +34,18 @@ class BaseAsyncIOLoop(IOLoop):
     def close(self, all_fds=False):
         self.closing = True
         for fd in list(self.handlers):
+            fileobj, handler_func = self.handlers[fd]
             self.remove_handler(fd)
             if all_fds:
-                self.close_fd(fd)
+                self.close_fd(fileobj)
         if self.close_loop:
             self.asyncio_loop.close()
 
     def add_handler(self, fd, handler, events):
+        fd, fileobj = self.split_fd(fd)
         if fd in self.handlers:
             raise ValueError("fd %s added twice" % fd)
-        self.handlers[fd] = stack_context.wrap(handler)
+        self.handlers[fd] = (fileobj, stack_context.wrap(handler))
         if events & IOLoop.READ:
             self.asyncio_loop.add_reader(
                 fd, self._handle_events, fd, IOLoop.READ)
@@ -54,6 +56,7 @@ class BaseAsyncIOLoop(IOLoop):
             self.writers.add(fd)
 
     def update_handler(self, fd, events):
+        fd, fileobj = self.split_fd(fd)
         if events & IOLoop.READ:
             if fd not in self.readers:
                 self.asyncio_loop.add_reader(
@@ -74,6 +77,7 @@ class BaseAsyncIOLoop(IOLoop):
                 self.writers.remove(fd)
 
     def remove_handler(self, fd):
+        fd, fileobj = self.split_fd(fd)
         if fd not in self.handlers:
             return
         if fd in self.readers:
@@ -85,7 +89,8 @@ class BaseAsyncIOLoop(IOLoop):
         del self.handlers[fd]
 
     def _handle_events(self, fd, events):
-        self.handlers[fd](fd, events)
+        fileobj, handler_func = self.handlers[fd]
+        handler_func(fileobj, events)
 
     def start(self):
         self._setup_logging()
index 3e888d3ddc2c56c7b2ff2afc42e6720dcc926ec8..460dc50f7461cf9b57835de989cfc41fada41442 100644 (file)
@@ -223,6 +223,18 @@ class TestIOLoop(AsyncTestCase):
         self.io_loop.remove_handler(server_sock.fileno())
         server_sock.close()
 
+    def test_mixed_fd_fileobj(self):
+        server_sock, port = bind_unused_port()
+        def f(fd, events):
+            pass
+        self.io_loop.add_handler(server_sock, f, IOLoop.READ)
+        with self.assertRaises(Exception):
+            # The exact error is unspecified - some implementations use
+            # IOError, others use ValueError.
+            self.io_loop.add_handler(server_sock.fileno(), f, IOLoop.READ)
+        self.io_loop.remove_handler(server_sock.fileno())
+        server_sock.close()
+
 
 
 # Deliberately not a subclass of AsyncTestCase so the IOLoop isn't