Permalink
Browse files

Ensure that add_callback fails cleanly if called while IOLoop is clos…

…ing.

Previously there would (sometimes) be an exception when writing to the
waker pipe.

Closes #635.
  • Loading branch information...
1 parent e7485f8 commit b724652105c82f9aaec006cf61e04c3771119735 @bdarnell bdarnell committed Nov 17, 2012
Showing with 24 additions and 0 deletions.
  1. +5 −0 tornado/ioloop.py
  2. +19 −0 tornado/test/ioloop_test.py
View
@@ -406,6 +406,7 @@ def initialize(self, impl, time_func=None):
self._timeouts = []
self._running = False
self._stopped = False
+ self._closing = False
self._thread_ident = None
self._blocking_signal_threshold = None
@@ -417,6 +418,8 @@ def initialize(self, impl, time_func=None):
self.READ)
def close(self, all_fds=False):
+ with self._callback_lock:
+ self._closing = True
self.remove_handler(self._waker.fileno())
if all_fds:
for fd in self._handlers.keys()[:]:
@@ -608,6 +611,8 @@ def remove_timeout(self, timeout):
def add_callback(self, callback):
with self._callback_lock:
+ if self._closing:
+ raise RuntimeError("IOLoop is closing")
list_empty = not self._callbacks
self._callbacks.append(stack_context.wrap(callback))
if list_empty and thread.get_ident() != self._thread_ident:
@@ -82,6 +82,25 @@ def test_add_callback_from_signal_other_thread(self):
thread.join()
other_ioloop.close()
+ def test_add_callback_while_closing(self):
+ # Issue #635: add_callback() should raise a clean exception
+ # if called while another thread is closing the IOLoop.
+ closing = threading.Event()
+ def target():
+ other_ioloop.add_callback(other_ioloop.stop)
+ other_ioloop.start()
+ closing.set()
+ other_ioloop.close(all_fds=True)
+ other_ioloop = IOLoop()
+ thread = threading.Thread(target=target)
+ thread.start()
+ closing.wait()
+ for i in range(1000):
+ try:
+ other_ioloop.add_callback(lambda: None)
+ except RuntimeError, e:
+ self.assertEqual("IOLoop is closing", str(e))
+ break
class TestIOLoopFutures(AsyncTestCase):
def test_add_future_threads(self):

0 comments on commit b724652

Please sign in to comment.