@@ -69,7 +69,11 @@ async def staggered_race(coro_fns, delay, *, loop=None):
6969 exceptions = []
7070 running_tasks = []
7171
72- async def run_one_coro (previous_failed ) -> None :
72+ async def run_one_coro (ok_to_start , previous_failed ) -> None :
73+ # in eager tasks this waits for the calling task to append this task
74+ # to running_tasks, in regular tasks this wait is a no-op that does
75+ # not yield a future. See gh-124309.
76+ await ok_to_start .wait ()
7377 # Wait for the previous task to finish, or for delay seconds
7478 if previous_failed is not None :
7579 with contextlib .suppress (exceptions_mod .TimeoutError ):
@@ -85,8 +89,12 @@ async def run_one_coro(previous_failed) -> None:
8589 return
8690 # Start task that will run the next coroutine
8791 this_failed = locks .Event ()
88- next_task = loop .create_task (run_one_coro (this_failed ))
92+ next_ok_to_start = locks .Event ()
93+ next_task = loop .create_task (run_one_coro (next_ok_to_start , this_failed ))
8994 running_tasks .append (next_task )
95+ # next_task has been appended to running_tasks so next_task is ok to
96+ # start.
97+ next_ok_to_start .set ()
9098 assert len (running_tasks ) == this_index + 2
9199 # Prepare place to put this coroutine's exceptions if not won
92100 exceptions .append (None )
@@ -116,8 +124,11 @@ async def run_one_coro(previous_failed) -> None:
116124 if i != this_index :
117125 t .cancel ()
118126
119- first_task = loop .create_task (run_one_coro (None ))
127+ ok_to_start = locks .Event ()
128+ first_task = loop .create_task (run_one_coro (ok_to_start , None ))
120129 running_tasks .append (first_task )
130+ # first_task has been appended to running_tasks so first_task is ok to start.
131+ ok_to_start .set ()
121132 try :
122133 # Wait for a growing list of tasks to all finish: poor man's version of
123134 # curio's TaskGroup or trio's nursery
0 commit comments