Skip to content

Commit

Permalink
Make AddThreadEventLoop.close() idempotent
Browse files Browse the repository at this point in the history
according to spec: https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.close

The call to _wake_selector would fail with EBADF when close is called a second time
  • Loading branch information
minrk committed May 19, 2021
1 parent 289c834 commit 63ae59d
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 0 deletions.
5 changes: 5 additions & 0 deletions tornado/platform/asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,8 @@ class SelectorThread:
but can be attached to a running asyncio loop.
"""

_closed = False

def __init__(self, real_loop: asyncio.AbstractEventLoop) -> None:
self._real_loop = real_loop

Expand Down Expand Up @@ -456,6 +458,8 @@ def __del__(self) -> None:
self._waker_w.close()

def close(self) -> None:
if self._closed:
return
with self._select_cond:
self._closing_selector = True
self._select_cond.notify()
Expand All @@ -464,6 +468,7 @@ def close(self) -> None:
_selector_loops.discard(self)
self._waker_r.close()
self._waker_w.close()
self._closed = True

def _wake_selector(self) -> None:
try:
Expand Down
6 changes: 6 additions & 0 deletions tornado/test/asyncio_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
AsyncIOLoop,
to_asyncio_future,
AnyThreadEventLoopPolicy,
AddThreadSelectorEventLoop,
)
from tornado.testing import AsyncTestCase, gen_test

Expand Down Expand Up @@ -107,6 +108,11 @@ async def native_coroutine_with_adapter2():
42,
)

def test_add_thread_close_idempotent(self):
loop = AddThreadSelectorEventLoop(asyncio.get_event_loop())
loop.close()
loop.close()


class LeakTest(unittest.TestCase):
def setUp(self):
Expand Down

0 comments on commit 63ae59d

Please sign in to comment.