From e964f989399b6a961b3e97e723f03fbe5fc620bc Mon Sep 17 00:00:00 2001 From: Ben Darnell Date: Sat, 13 Jan 2018 17:31:32 -0500 Subject: [PATCH] ioloop,asyncio: Be more careful to restore old asyncio loop Any asyncio event loop that was created but neither closed nor set as current for some thread will log a warning at the end of the test (in a way that doesn't cause the test to fail). Fix a bug in make_current() (in which multiple calls would clobber self.old_asyncio) and use it more consistently when "current" status changes. --- tornado/ioloop.py | 13 ++++++++++--- tornado/platform/asyncio.py | 22 ++++++++++++++++------ 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/tornado/ioloop.py b/tornado/ioloop.py index c829afcf5..b17f24bd9 100644 --- a/tornado/ioloop.py +++ b/tornado/ioloop.py @@ -310,6 +310,9 @@ class IOLoop(Configurable): .. versionchanged:: 5.0 This method also sets the current `asyncio` event loop. """ + old = getattr(IOLoop._current, "instance", None) + if old is not None: + old.clear_current() IOLoop._current.instance = self @staticmethod @@ -924,8 +927,9 @@ class PollIOLoop(IOLoop): if self._stopped: self._stopped = False return - old_current = getattr(IOLoop._current, "instance", None) - IOLoop._current.instance = self + old_current = IOLoop.current(instance=False) + if old_current is not self: + self.make_current() self._thread_ident = thread.get_ident() self._running = True @@ -1068,7 +1072,10 @@ class PollIOLoop(IOLoop): self._stopped = False if self._blocking_signal_threshold is not None: signal.setitimer(signal.ITIMER_REAL, 0, 0) - IOLoop._current.instance = old_current + if old_current is None: + IOLoop.clear_current() + elif old_current is not self: + old_current.make_current() if old_wakeup_fd is not None: signal.set_wakeup_fd(old_wakeup_fd) diff --git a/tornado/platform/asyncio.py b/tornado/platform/asyncio.py index ac0946cd7..d28a491db 100644 --- a/tornado/platform/asyncio.py +++ b/tornado/platform/asyncio.py @@ -186,6 +186,7 @@ class AsyncIOLoop(BaseAsyncIOLoop): to refer to this class directly. """ def initialize(self, **kwargs): + self.is_current = False loop = asyncio.new_event_loop() try: super(AsyncIOLoop, self).initialize(loop, **kwargs) @@ -195,16 +196,25 @@ class AsyncIOLoop(BaseAsyncIOLoop): loop.close() raise + def close(self, all_fds=False): + if self.is_current: + self.clear_current() + super(AsyncIOLoop, self).close(all_fds=all_fds) + def make_current(self): - super(AsyncIOLoop, self).make_current() - try: - self.old_asyncio = asyncio.get_event_loop() - except RuntimeError: - self.old_asyncio = None + if not self.is_current: + super(AsyncIOLoop, self).make_current() + try: + self.old_asyncio = asyncio.get_event_loop() + except RuntimeError: + self.old_asyncio = None + self.is_current = True asyncio.set_event_loop(self.asyncio_loop) def _clear_current_hook(self): - asyncio.set_event_loop(self.old_asyncio) + if self.is_current: + asyncio.set_event_loop(self.old_asyncio) + self.is_current = False def to_tornado_future(asyncio_future): -- 2.47.2