Skip to content

gh-149123: Avoid InvalidStateError in Windows Proactor polling#152852

Open
zainnadeem786 wants to merge 1 commit into
python:mainfrom
zainnadeem786:fix/asyncio-proactor-invalidstate-win995
Open

gh-149123: Avoid InvalidStateError in Windows Proactor polling#152852
zainnadeem786 wants to merge 1 commit into
python:mainfrom
zainnadeem786:fix/asyncio-proactor-invalidstate-win995

Conversation

@zainnadeem786

Copy link
Copy Markdown
Contributor

Summary

This PR addresses the race condition described in gh-149123.

IocpProactor._poll() checks whether an _OverlappedFuture is pending before invoking its completion callback. However, the callback may eventually call Overlapped.getresult(), which releases the GIL while waiting for the underlying Windows I/O completion.

During that window, another thread may complete or cancel the same future. When _poll() resumes, the subsequent call to Future.set_exception() or Future.set_result() can therefore raise asyncio.InvalidStateError, even though the future was pending before the callback started.

This change re-checks the future state immediately before setting the result or exception. If the future became done while the callback was executing, _poll() simply skips result delivery, matching the existing behavior for futures that are already done before callback execution.

No public API or observable behavior is otherwise changed.

Tests

Adds deterministic regression tests covering both execution paths:

  • Future becomes done during the callback before set_exception()
  • Future becomes done during the callback before set_result()

Both tests verify that _poll() no longer raises asyncio.InvalidStateError when the future transitions to a completed state during callback execution.

Validation

Validated using a Windows debug build of current main.

Targeted regression tests:

PCbuild\amd64\python_d.exe -m unittest -v \
test.test_asyncio.test_windows_events.ProactorTests.test_poll_skips_exception_if_future_done_during_callback \
test.test_asyncio.test_windows_events.ProactorTests.test_poll_skips_result_if_future_done_during_callback

Both regression tests pass.

Additional validation:

git diff --check

passed successfully.

A broader local test_asyncio run encountered unrelated Windows environment permission failures involving named pipes and temporary-directory cleanup, but the new regression tests completed successfully.

Changes

  • Re-check Future.done() after the completion callback returns or raises.
  • Skip calling set_exception() or set_result() if the future became done during callback execution.
  • Add deterministic regression tests covering both exception and success paths.
  • Add a NEWS entry.

Fixes gh-149123.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

asyncio on Windows raises InvalidStateError after WinError 995

1 participant