I was looking through a Python implementation of socketpair that uses standard sockets. Here's the code snippet I found:
def socketpair(family=AF_INET, type=SOCK_STREAM, proto=0):
if family == AF_INET:
host = _LOCALHOST
elif family == AF_INET6:
host = _LOCALHOST_V6
else:
raise ValueError("Only AF_INET and AF_INET6 socket address families "
"are supported")
if type != SOCK_STREAM:
raise ValueError("Only SOCK_STREAM socket type is supported")
if proto != 0:
raise ValueError("Only protocol zero is supported")
# We create a connected TCP socket. Note the trick with
# setblocking(False) that prevents us from having to create a thread.
lsock = socket(family, type, proto)
try:
lsock.bind((host, 0))
lsock.listen()
addr, port = lsock.getsockname()[:2]
csock = socket(family, type, proto)
try:
csock.setblocking(False)
try:
csock.connect((addr, port))
except (BlockingIOError, InterruptedError):
pass
csock.setblocking(True)
ssock, _ = lsock.accept()
except:
csock.close()
raise
finally:
lsock.close()
return (ssock, csock)
The implementation mentions that setblocking(False)
is necessary to "prevent us from having to create a thread," but I can't seem to understand why this is required.
I initially thought that omitting setblocking(False)
could lead to a deadlock or blocking behavior, but after testing on both Linux and Windows, the code seems to work fine without it, and the connect call does not block.
So my question is:
setblocking(False)
intended to solve here?setblocking(False)
would cause problems?Any insight into this behavior would be greatly appreciated.
The code is initiating a non-blocking connect to another socket within the same thread, i.e.
The non-blocking connect in (2) returns immediately, even if the socket is not yet accepted (3). If instead a blocking connect would be used then it would hang in (2) until accept gets called in (3), which would never happen because it hangs in (2).
The alternative would be to do a blocking connect and a blocking accept in separate threads. Hence the comment:
# ... Note the trick with
# setblocking(False) that prevents us from having to create a thread