-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
Description
Bug report
Bug description:
I'm working on a Debian bookworm system. Please consider this executable script ms
:
#!/usr/bin/python3 -i
from pathlib import Path
import socket
SOCK = 'stream.sock'
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
Path(SOCK).unlink(missing_ok=True)
s.bind(SOCK)
s.listen(0)
and this one mc
:
#!/usr/bin/python3
import socket
SOCK = 'stream.sock'
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.settimeout(3)
s.connect(SOCK)
Let's start ./ms
, and once it reaches the Python prompt, run ./mc
twice in another terminal:
$ ./mc
$ ./mc
Traceback (most recent call last):
File "/home/wferi/block/./mc", line 8, in <module>
s.connect(SOCK)
BlockingIOError: [Errno 11] Resource temporarily unavailable
The first1 invocation runs to completion all right, but all succeeding ones immediately fail with BlockingIOError
, as if the connecting socket was in non-blocking mode, not in timeout mode. I understand that the documentation2 notes
at the operating system level, sockets in timeout mode are internally set in non-blocking mode
so that must be where this comes from, but such an implementation detail shouldn't leak out of the abstraction, as the documentation also states that
A socket object can be in one of three modes: blocking, non-blocking, or timeout.
and
exception BlockingIOError: Raised when an operation would block on an object (e.g. socket) set for non-blocking operation. 3
CPython versions tested on:
3.11
Operating systems tested on:
Linux
Linked PRs
Footnotes
-
In general the first backlog+1, but I set the listen backlog to 0 in the code of
ms
above. ↩ -
https://docs.python.org/3/library/socket.html#socket-timeouts ↩
Activity
duaneg commentedon May 26, 2025
I found this unreliable to reproduce initially, but after some tweaking managed to come up with a self-contained script that works on my system:
repro
The exception is coming from
internal_connect
, where it callsconnect
. If there is a timeout andconnect
fails withEINPROGRESS
, we wait. However,man 2 connect
on Linux tells us:That is what is happening in this case. Since it is a UNIX domain socket
errno
is set toEAGAIN
notEINPROGRESS
, so it doesn't try to wait, and immediately raises the error.pythongh-117208: handle EAGAIN in non-blocking connect