Permalink
Browse files

Disallow multiple calls to add_handler for the same fd in IOLoop.

This was already true for epoll; this change adds a check for
kqueue and select implementations.
  • Loading branch information...
bdarnell committed Jun 29, 2012
1 parent cfd7a96 commit ed7030d280962a2ba5a9861689eecd6edbabfd94
Showing with 24 additions and 2 deletions.
  1. +4 −0 tornado/ioloop.py
  2. +20 −2 tornado/test/ioloop_test.py
View
@@ -553,6 +553,8 @@ def close(self):
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 @@ def close(self):
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:
@@ -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 @@ def test_add_timeout_timedelta(self):
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()

0 comments on commit ed7030d

Please sign in to comment.