self._timeouts = []
self._running = False
self._stopped = False
+ self._closing = False
self._thread_ident = None
self._blocking_signal_threshold = 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()[:]:
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:
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):