Skip to content

docs: explain the Windows asyncio socketpair requirement - #569

Open
simin-yuan wants to merge 3 commits into
miketheman:mainfrom
simin-yuan:docs/windows-asyncio-socketpair
Open

simin-yuan wants to merge 3 commits into
miketheman:mainfrom
simin-yuan:docs/windows-asyncio-socketpair

Conversation

@simin-yuan

Copy link
Copy Markdown

Closes #568

Summary

On Windows, --disable-socket also blocks the AF_INET loopback pair that
asyncio builds for its self-pipe, so every async test fails during setup with
SocketBlockedError. This adds an FAQ entry to the README that names the
failure, shows the configuration that works, and states that outbound
connections stay blocked.

Why

_socket has no socketpair() on Windows, so socket.socketpair() takes the
pure-Python path: it binds an AF_INET listener on 127.0.0.1, connects a
second socket to it, and returns the pair. The guard blocks that connection,
so asyncio.new_event_loop() raises before the test runs.

Measured

Windows 11, CPython 3.11.16, 3.12.14 and 3.13.13, pytest 9.2.0,
pytest-socket 0.8.1, three-test probe (create a loop,
socket.socketpair() round trip, one @pytest.mark.asyncio test):

configuration 3.11.16 3.12.14 3.13.13
no flags 3 passed 3 passed 3 passed
--disable-socket 2 failed, 1 error 2 failed, 1 error 2 failed, 1 error
--disable-socket --allow-hosts=127.0.0.1 3 passed 3 passed 3 passed
--disable-socket --allow-hosts=127.0.0.1,::1 3 passed 3 passed 3 passed
--disable-socket --allow-unix-socket 2 failed, 1 error 2 failed, 1 error 2 failed, 1 error
--disable-socket --allow-unix-socket --allow-hosts=127.0.0.1,::1 3 passed 3 passed 3 passed

With --disable-socket --allow-hosts=127.0.0.1,::1,
socket.create_connection(("192.0.2.1", 80)) still raises
pytest_socket.SocketConnectBlockedError; the same call fails when no blocker
is active, so the check is a real one and not an artefact of the address.

Scope

Documentation only, no code change, no test change. A narrower alternative,
exempting just the pair created inside socketpair() so loopback stays blocked
for user code, is proposed in kiwicom/pytest-recording#213 (still open) and can
be done separately if you prefer that to the documented workaround.

Related: kiwicom/pytest-recording#212, kiwicom/pytest-recording#213.

--disable-socket also blocks the loopback pair that asyncio builds for its
self-pipe on Windows, so every async test fails during setup with
SocketBlockedError. Record the working configuration, note that
--allow-unix-socket does not apply, and show that outbound connections stay
blocked.

See kiwicom/pytest-recording#212 and kiwicom/pytest-recording#213 for the
same failure in another network-blocking plugin.

Signed-off-by: Simin Yuan <281164480+simin-yuan@users.noreply.github.com>
@simin-yuan

Copy link
Copy Markdown
Author

For reference, pytest-recording took the same approach and shipped it in 0.14.1 (kiwicom/pytest-recording#213).

--allow-hosts skips disable_socket() entirely (pytest_runtest_setup,
__init__.py:220), so socket() and the DNS helpers stay unpatched and only
connect() keeps the allow-list check. Found by @mgkvibez in miketheman#568.

Signed-off-by: Simin Yuan <281164480+simin-yuan@users.noreply.github.com>

This branch has not been deployed

No deployments
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.

--disable-socket blocks socketpair(), breaking asyncio event loops on POSIX and Windows

1 participant