From d11daaa89088a78615d7ea523a17e757271303af Mon Sep 17 00:00:00 2001 From: Alexander Clausen Date: Sat, 12 Dec 2020 06:58:06 +0100 Subject: [PATCH] WaitIterator: don't re-use _running_future When used with asyncio.Future, WaitIterator may skip indices in some cases. This is caused by multiple _return_result calls after another, without having the chain_future call finish in between. This is fixed here by not hanging on to the _running_future anymore, which forces subsequent _return_result calls to add to _finished, instead of causing the previous result to be silently dropped. Fixes #2034 --- tornado/gen.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tornado/gen.py b/tornado/gen.py index cab9689375..2d20385513 100644 --- a/tornado/gen.py +++ b/tornado/gen.py @@ -400,7 +400,7 @@ def next(self) -> Future: self._running_future = Future() if self._finished: - self._return_result(self._finished.popleft()) + return self._return_result(self._finished.popleft()) return self._running_future @@ -418,9 +418,13 @@ def _return_result(self, done: Future) -> None: raise Exception("no future is running") chain_future(done, self._running_future) + res = self._running_future + self._running_future = None self.current_future = done self.current_index = self._unfinished.pop(done) + return res + def __aiter__(self) -> typing.AsyncIterator: return self