Hi all,
I recently realized that when a future is yielded, `Task._wakeup` is added
as a done callback without checking that their loops are the same. That
means that `Task._wakeup` might end up being called in the future loop
instead of its own loop, which seems wrong. Is there a reason not to check
this in `Task._step`?
def _step(self, exc=None):
[...]
if isinstance(result, futures.Future):
if self._loop is not result._loop:
self._loop.call_soon(
self._step,
RuntimeError(
'a future using a different loop has been yielded')
A common mistake is to forget the `loop` argument when using a different
loop than the one provided by `asyncio.get_event_loop`:
async def coro():
await asyncio.sleep(3)
loop = asyncio.new_event_loop()
loop.run_until_complete(coro())
This code blocks forever, since the `sleep` is scheduled in a different
event loop. It can be quite painful to debug, especially for someone
experimenting with asyncio for the first time. But with the modification
proposed above, this example would raise the following exception instead:
RuntimeError: a future using a different loop has been yielded
Part of the problem is also that one might expect the current loop to be
used, while it actually defaults to the result of `asyncio.get_event_loop`.
Has this issue been discussed already?
Thanks.