Race condition when using AsyncTimeout · Issue #459 · pytransitions/transitions (original) (raw)
Consider the following example:
import asyncio
from transitions.extensions.asyncio import AsyncMachine, AsyncTimeout from transitions.extensions.states import add_state_features
@add_state_features(AsyncTimeout) class CustomMachine(AsyncMachine): pass
class Model: async def on_enter_completed(self): print('entered completed state')
async def on_enter_waiting(self):
print('entered waiting state')
async def main(): model = Model()
states = [
'start',
{ 'name': 'waiting', 'timeout': 0.5, 'on_timeout': 'to_waiting' },
'completed',
]
machine = CustomMachine(model, states, initial='start')
machine.add_transition('wait', 'start', 'waiting')
machine.add_transition('complete', 'waiting', 'completed')
await model.wait()
await asyncio.sleep(1.0)
await model.complete()
loop = asyncio.get_event_loop() loop.create_task(main()) loop.run_forever() loop.close()
The intended behavior is for it to loop on the waiting
state a few times, then transition to the completed
state and stop. However, the output looks like this:
entered waiting state
entered waiting state
entered completed state
entered waiting state
entered waiting state
entered waiting state
entered waiting state
[...repeats forever...]
It seems that the timer that transitions back to the waiting
state does not get properly canceled when we transition to the completed
state.