Skip to content
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

[3.7] bpo-32751: Wait for task cancellation in asyncio.wait_for() (GH-7216) #7223

Merged
merged 1 commit into from
May 29, 2018

Conversation

miss-islington
Copy link
Contributor

@miss-islington miss-islington commented May 29, 2018

Currently, asyncio.wait_for(fut), upon reaching the timeout deadline,
cancels the future and returns immediately. This is problematic for
when fut is a Task, because it will be left running for an arbitrary
amount of time. This behavior is iself surprising and may lead to
related bugs such as the one described in bpo-33638:

condition = asyncio.Condition()
async with condition:
    await asyncio.wait_for(condition.wait(), timeout=0.5)

Currently, instead of raising a TimeoutError, the above code will fail
with RuntimeError: cannot wait on un-acquired lock, because
__aexit__ is reached before condition.wait() finishes its
cancellation and re-acquires the condition lock.

To resolve this, make wait_for await for the task cancellation.
The tradeoff here is that the timeout promise may be broken if the
task decides to handle its cancellation in a slow way. This represents
a behavior change and should probably not be back-patched to 3.6 and
earlier.
(cherry picked from commit e2b340a)

Co-authored-by: Elvis Pranskevichus elvis@magic.io

https://bugs.python.org/issue32751

…-7216)

Currently, asyncio.wait_for(fut), upon reaching the timeout deadline,
cancels the future and returns immediately.  This is problematic for
when *fut* is a Task, because it will be left running for an arbitrary
amount of time.  This behavior is iself surprising and may lead to
related bugs such as the one described in bpo-33638:

    condition = asyncio.Condition()
    async with condition:
        await asyncio.wait_for(condition.wait(), timeout=0.5)

Currently, instead of raising a TimeoutError, the above code will fail
with `RuntimeError: cannot wait on un-acquired lock`, because
`__aexit__` is reached _before_ `condition.wait()` finishes its
cancellation and re-acquires the condition lock.

To resolve this, make `wait_for` await for the task cancellation.
The tradeoff here is that the `timeout` promise may be broken if the
task decides to handle its cancellation in a slow way.  This represents
a behavior change and should probably not be back-patched to 3.6 and
earlier.
(cherry picked from commit e2b340a)

Co-authored-by: Elvis Pranskevichus <elvis@magic.io>
@miss-islington
Copy link
Contributor Author

@elprans and @1st1: Backport status check is done, and it's a success ✅ .

@miss-islington miss-islington merged commit d8948c5 into python:3.7 May 29, 2018
@miss-islington
Copy link
Contributor Author

Thanks!

@miss-islington miss-islington deleted the backport-e2b340a-3.7 branch May 29, 2018 22:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants