Update drain_queues to check if queue has already been drained #49
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I'm seeing some exception log messages when using the GeventScheduler.
This issue can be reproduced with this code:
The problem occurs when
then
is called on a promise followed by aget
.then
queues a job on the gevent event loop to settle the target promise using:When this happens,
target._settle_promise
is put on the processing queue andasync_.py::Async::queue_tick
is called. That in turn putsasync_.py::Async::drain_queues
on the gevent event loop.Nothing has yielded to the gevent event loop yet, so the main greenlet is still running. When
get
is called on the promiseasync_.py::Async::wait
is called, that drains the queues usingdrain_queue_until_resolved
. The promise is now settled sincepartial(target._settle_promise, promise, handler, value, traceback)
was on the async queue. This also flips the flag indicating that the tick has been used and the queues are empty.When get returns the settled value of the promise chain the greenlet will eventually yield to the gevent event loop and
async_.py::Async::drain_queues
will run. An assertion error will be thrown since the queue has already been processed.I've fixed this by removing the assert check and just checking if the tick has already been processed or not in
async_.py::Async::drain_queues
.An alternative to this fix is to remove the trampoline logic or disable it when used with gevent, although I think this would happen with most other async libs as well. Removing the trampoline logic would result in work being put on the event loop directly instead of executing in a single job when the queue is drained in
async_.py
.