This is continued from: Asyncio timeout on event wait in “help” section.
When adding a timeout to asyncio.Event.wait in order to get either an event notificaton or a timeout, we could write:
try:
async with asyncio.timeout(delay):
await event.wait()
except TimeoutError:
print("No event")
else:
print("Event!")
However, following can happen in this code block:
- the timeout occurs internally (scheduled
call_latercallback is executed) - then another task sets the event
- then
__aexit__of the async context manager handles the timeout from 1. - program prints “No event” - which is not true after 2.
It’s a classic check-then-act race condition, but IMO not at all obvious, because it is hidden in implementation. I think this should get some attention, because it’s a possible source of bugs. But if you think the opposite and we should do nothing, please respond too.
Options are:
- provide an atomic timeout handling for single operations naturally expected either to succed or to raise. Examples:
event.waitorqueue.get(I didn’t check). By atomic I mean that timeout handling cannot be interleaved with other tasks running and possibly changing the outcome of the operation. This would be nice, but maybe difficult or not possible. - add a note to the documentation