Skip to content

Conversation

@zmedico
Copy link
Member

@zmedico zmedico commented Dec 6, 2020

Make the _safe_loop function return an AsyncioEventLoop instance,
so that the default asyncio event loop implementation will be used
in API consumer threads. This is possible because the underlying
asyncio.get_event_loop() function returns a separate event loop for
each thread. The AsyncioEventLoop _run_until_complete method will
now appropriately handle a ValueError from signal.set_wakeup_fd(-1)
if it is not called in the main thread.

For external API consumers calling from a non-main thread, an
asyncio loop must be registered for the current thread, or else an
error will be raised like this:

RuntimeError: There is no current event loop in thread 'Thread-1'.

In order to avoid this RuntimeError, the external API consumer
is responsible for setting an event loop and managing its lifecycle.
For example, this code will set an event loop for the current thread:

asyncio.set_event_loop(asyncio.new_event_loop())

In order to avoid a ResourceWarning, the caller should also close
the corresponding loop before the current thread terminates.

Bug: https://bugs.gentoo.org/758755
Signed-off-by: Zac Medico [email protected]

@zmedico zmedico force-pushed the bug_758755_use_default_asyncio_event_loop_in_thread branch 3 times, most recently from 8d1d3fa to 6342dd5 Compare December 7, 2020 01:14
Make the _safe_loop function return an AsyncioEventLoop instance,
so that the default asyncio event loop implementation will be used
in API consumer threads. This is possible because the underlying
asyncio.get_event_loop() function returns a separate  event loop for
each thread. The AsyncioEventLoop _run_until_complete method will
now appropriately handle a ValueError from signal.set_wakeup_fd(-1)
if it is not called in the main thread.

For external API consumers calling from a non-main thread, an
asyncio loop must be registered for the current thread, or else an
error will be raised like this:

  RuntimeError: There is no current event loop in thread 'Thread-1'.

In order to avoid this RuntimeError, the external API consumer
is responsible for setting an event loop and managing its lifecycle.
For example, this code will set an event loop for the current thread:

  asyncio.set_event_loop(asyncio.new_event_loop())

In order to avoid a ResourceWarning, the caller should also close
the corresponding loop before the current thread terminates.

Bug: https://bugs.gentoo.org/758755
Signed-off-by: Zac Medico <[email protected]>
@zmedico zmedico force-pushed the bug_758755_use_default_asyncio_event_loop_in_thread branch from 6342dd5 to cecd2f8 Compare December 7, 2020 02:32
@gentoo-bot gentoo-bot merged commit cecd2f8 into gentoo:master Dec 7, 2020
@zmedico zmedico deleted the bug_758755_use_default_asyncio_event_loop_in_thread branch December 7, 2020 02:52
@zmedico
Copy link
Member Author

zmedico commented Dec 7, 2020

If an asyncio loop is not running in the main thread, then API consumer threads will not work in practice with less than python3.8, since https://bugs.python.org/issue35621 makes MultiLoopChildWatcher necessary in order to avoid RuntimeError: Cannot add child handler, the child watcher does not have a loop attached.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants