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

Fix TaskInfo.has_pending_cancellation() false positives on asyncio with shielding #772

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/versionhistory.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ This library adheres to `Semantic Versioning 2.0 <http://semver.org/>`_.
- Fixed ``to_process.run_sync()`` failing to initialize if ``__main__.__file__`` pointed
to a file in a nonexistent directory
(`#696 <https://github.com/agronholm/anyio/issues/696>`_)
- Fixed ``TaskInfo.has_pending_cancellation()`` on asyncio not respecting shielded
scopes (`#771 <https://github.com/agronholm/anyio/issues/771>`_; PR by @gschaffner)

**4.4.0**

Expand Down
4 changes: 3 additions & 1 deletion src/anyio/_backends/_asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -1861,7 +1861,9 @@ def has_pending_cancellation(self) -> bool:

if task_state := _task_states.get(task):
if cancel_scope := task_state.cancel_scope:
return cancel_scope.cancel_called or cancel_scope._parent_cancelled()
return cancel_scope.cancel_called or (
not cancel_scope.shield and cancel_scope._parent_cancelled()
)

return False

Expand Down
3 changes: 3 additions & 0 deletions tests/test_taskgroups.py
Original file line number Diff line number Diff line change
Expand Up @@ -628,9 +628,11 @@ async def test_cancel_from_shielded_scope() -> None:
assert inner_scope.shield
tg.cancel_scope.cancel()
assert current_effective_deadline() == math.inf
assert not get_current_task().has_pending_cancellation()
await checkpoint()

assert current_effective_deadline() == -math.inf
assert get_current_task().has_pending_cancellation()

with pytest.raises(get_cancelled_exc_class()):
await sleep(0.01)
Expand All @@ -644,6 +646,7 @@ async def test_cancel_shielded_scope() -> None:
assert cancel_scope.shield
cancel_scope.cancel()
assert current_effective_deadline() == -math.inf
assert get_current_task().has_pending_cancellation()

with pytest.raises(get_cancelled_exc_class()):
await checkpoint()
Expand Down
Loading