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.



Reply via email to