]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Disallow multiple calls to add_handler for the same fd in IOLoop.
authorBen Darnell <ben@bendarnell.com>
Fri, 29 Jun 2012 07:53:22 +0000 (00:53 -0700)
committerBen Darnell <ben@bendarnell.com>
Fri, 29 Jun 2012 07:53:22 +0000 (00:53 -0700)
This was already true for epoll; this change adds a check for
kqueue and select implementations.

tornado/ioloop.py
tornado/test/ioloop_test.py

index 3e14229898f57c471745bc74bc5014be188e905f..70eb5564b217d8e5fbf199bc33916f3d451e679a 100644 (file)
@@ -553,6 +553,8 @@ class _KQueue(object):
         self._kqueue.close()
 
     def register(self, fd, events):
+        if fd in self._active:
+            raise IOError("fd %d already registered" % fd)
         self._control(fd, events, select.KQ_EV_ADD)
         self._active[fd] = events
 
@@ -614,6 +616,8 @@ class _Select(object):
         pass
 
     def register(self, fd, events):
+        if fd in self.read_fds or fd in self.write_fds or fd in self.error_fds:
+            raise IOError("fd %d already registered" % fd)
         if events & IOLoop.READ:
             self.read_fds.add(fd)
         if events & IOLoop.WRITE:
index df2cd77710737a7ea9d8652f86fcee4cd0de0e0c..2ebdbcea82ad229825a02bed68f2f5ff9dc4eebe 100644 (file)
@@ -3,10 +3,13 @@
 
 from __future__ import absolute_import, division, with_statement
 import datetime
-import unittest
+import socket
 import time
+import unittest
 
-from tornado.testing import AsyncTestCase, LogTrapTestCase
+from tornado.ioloop import IOLoop
+from tornado.netutil import bind_sockets
+from tornado.testing import AsyncTestCase, LogTrapTestCase, get_unused_port
 
 
 class TestIOLoop(AsyncTestCase, LogTrapTestCase):
@@ -31,5 +34,20 @@ class TestIOLoop(AsyncTestCase, LogTrapTestCase):
         self.io_loop.add_timeout(datetime.timedelta(microseconds=1), self.stop)
         self.wait()
 
+    def test_multiple_add(self):
+        [sock] = bind_sockets(get_unused_port(), '127.0.0.1',
+                              family=socket.AF_INET)
+        try:
+            self.io_loop.add_handler(sock.fileno(), lambda fd, events: None,
+                                     IOLoop.READ)
+            # Attempting to add the same handler twice fails
+            # (with a platform-dependent exception)
+            self.assertRaises(Exception, self.io_loop.add_handler,
+                              sock.fileno(), lambda fd, events: None,
+                              IOLoop.READ)
+        finally:
+            sock.close()
+
+
 if __name__ == "__main__":
     unittest.main()