New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Confusing error during cyclic yield #72159
Comments
Below code reproduces the problem. The resulting error is a RecursionError and it is very hard to trace that to the cause of the problem, which is the runner task and the stop task yielding from each other, forming a deadlock. I think, an easy to make mistake like that should raise a clearer exception. And maybe I am mistaken, but it should in principle be possible for the event loop to detect a cyclic yield, right? import asyncio
class A:
@asyncio.coroutine
def start(self):
self.runner_task = asyncio.ensure_future(self.runner())
@asyncio.coroutine
def stop(self):
self.runner_task.cancel()
yield from self.runner_task
@asyncio.coroutine
def runner(self):
try:
while True:
yield from asyncio.sleep(5)
except asyncio.CancelledError:
yield from self.stop()
return
def do_test():
@asyncio.coroutine
def f():
a = A()
yield from a.start()
yield from asyncio.sleep(1)
yield from a.stop()
|
Thanks for the report. I've never seen this before, so I doubt it is a --Guido (mobile) |
This is an interesting mind twister. The key problem is that Therefore when the task is being cancelled, One way to solve this is to prohibit tasks to await on themselves. Right now the following code "kind of" works: async def f():
loop.call_later(1, lambda: t.set_result(42))
return await t
loop = asyncio.get_event_loop()
t = loop.create_task(f())
print(loop.run_until_complete(t)) albeit it logs errors about invalid Future state. My proposal is to raise a ValueError if Task is asked to await on itself. Guido, what do you think? |
It's pretty perverse. But how would you detect this case? Does it |
In Task._step, we can check if the future the task is about to await on is "self". |
Is that enough? What if the recursion involves several tasks waiting |
I'm not sure... Maybe it's OK when two tasks await on each other, I think the current Task implementation should be able to handle that. The problem with the Task awaiting itself is that the current implementation just crashes with a RecursionError. |
Maybe it could be fixed rather than making this a checked failure? |
I've meditated on this and I've changed my mind. A task that awaits IOW @1st1 I think it's okay to detect this and raise an exception. |
New changeset 8d877876aa89 by Yury Selivanov in branch '3.5': New changeset 41c4f535b5c0 by Yury Selivanov in branch '3.6': New changeset 47720192b318 by Yury Selivanov in branch 'default': |
Thank you for reporting this! Closing the issue. |
You are very welcome, glad I could help. |
Misc/NEWS
so that it is managed by towncrier #552Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: