-
-
Notifications
You must be signed in to change notification settings - Fork 31.8k
wait_for and Condition.wait still not playing nicely #83213
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This is related to https://bugs.python.org/issue22970, https://bugs.python.org/issue33638, and https://bugs.python.org/issue32751. I've replicated the issue on Python 3.6.9, 3.7.4, and 3.8.0. Looking at the source, I'm fairly sure the bug is still in master right now. The problem is yet another case of wait_for returning early, before the child has been fully cancelled and terminated. The issue arises if wait_for itself is cancelled. Take the following minimal example: cond = asyncio.Condition()
async def coro():
async with cond:
await asyncio.wait_for(cond.wait(), timeout=999) If coro is cancelled a few seconds after being run, wait_for will cancel the cond.wait(), then immediately re-raise the CancelledError inside coro, leading to "RuntimeError: Lock is not acquired." Relevant source code plucked from the 3.8 branch is as follows: try: if fut.done():
return fut.result()
else:
fut.remove_done_callback(cb)
# We must ensure that the task is not running
# after wait_for() returns.
# See https://bugs.python.org/issue32751
await _cancel_and_wait(fut, loop=loop)
raise exceptions.TimeoutError()
finally:
timeout_handle.cancel() Note how if the timeout occurs, the method waits for the future to complete before raising. If CancelledError is thrown, it doesn't. A simple fix seems to be replacing the "fut.cancel()" with "await _cancel_and_wait(fut, loop=loop)" so the behaviour is the same in both cases, however I'm only superficially familiar with the code, and am unsure if this would cause other problems. |
Its unlikely that https://bugs.python.org/issue39032 and python/cpython#83213 will be fixed soon. While we moved away from an asyncio.Condition, we still has a similar problem with waiting for an asyncio.Event which wait_event_or_timeout played well with. async_timeout avoids creating a task so its a bit more efficient. Since we call these when resolving ServiceInfo, avoiding task creation will resolve a performance problem when ServiceBrowsers startup as they tend to create task storms when coupled with ServiceInfo lookups.
Its unlikely that https://bugs.python.org/issue39032 and python/cpython#83213 will be fixed soon. While we moved away from an asyncio.Condition, we still has a similar problem with waiting for an asyncio.Event which wait_event_or_timeout played well with. async_timeout avoids creating a task so its a bit more efficient. Since we call these when resolving ServiceInfo, avoiding task creation will resolve a performance problem when ServiceBrowsers startup as they tend to create task storms when coupled with ServiceInfo lookups.
Closing is favor of the related #86296 |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: