QUERY · ISSUE
uasyncio emits no error message if a coro is called rather than awaited.
extmod
The following
import uasyncio as asyncio
async def bar():
await asyncio.sleep(1)
print('In bar')
async def foo():
print('Launching bar')
await bar()
print('Getting it wrong')
bar() # bad
loop = asyncio.get_event_loop()
loop.run_until_complete(foo())
produces this output
>>> import rats37
Launching bar
In bar
Getting it wrong
>>>
CPython 3.5.2 issues the following error message:
>>> import rats37
Launching bar
In bar
Getting it wrong
/home/adminpete/rats37.py:11: RuntimeWarning: coroutine 'bar' was never awaited
bar()
>>>
It would be useful if a message were emitted in response to this error.
CANDIDATE · PULL REQUEST
extmod/uasyncio/task.py: Fix crash when non-awaited task is awaited.
extmod
A task that has been sent to the loop's exception handler due to being re-scheduled twice will then subsequently cause a raise None if it is subsequently awaited. In the C version of task.py, this causes a segfault.
async def task():
raise Exception("task")
t = asyncio.create_task(task())
await asyncio.sleep(0)
await asyncio.sleep(0) # <-- loop exception handler called here
await t # <-- this line crashes
This PR makes the await succeed (via raising StopIteration instead).
I'm not sure this is the right fix though... it seems wrong to make the await succeed. The other option that I can think of are:
- Improve the logic for detecting the "un-awaited" task. Without reference counting this seems impossible.
- Make the task retain its exception, and even after it has been delivered to the loop's exception handler, still have await raise the original exception.
- Make the await raise CancelledError.
I think the third option (CancelledError) might be the most pragmatic alternative?