Open
Description
Bug report
Bug description:
We set up a multiprocessing.connection.Listener with no authkey. When we try to connect to it with a Client with an authkey, the Client deadlocks. Here is a working example:
import socket
import threading
import time
from multiprocessing.connection import Client, Listener
def _test(*, listener: str | None, client: str | None) -> tuple[Exception | None, Exception | None, list]:
_autkey_listener = listener.encode() if listener else None
_authkey_client = client.encode() if client else None
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(("localhost", 0))
address = s.getsockname()
thread_exc = None
thread_got = []
client_exc = None
def target() -> None:
try:
with Listener(address, authkey=_autkey_listener) as l:
c = l.accept()
while True:
value = c.recv()
if not value:
break
thread_got.append(value)
except Exception as e:
nonlocal thread_exc
thread_exc = e
t = threading.Thread(target=target)
t.start()
try:
with Client(address, authkey=_authkey_client) as c:
c.send("hello")
time.sleep(0.1)
c.send(None)
t.join()
except Exception as e:
client_exc = e
return thread_exc, client_exc, thread_got
if __name__ == "__main__":
print(" no passwords ".center(40, "-"))
print(_test(listener=None, client=None))
print(" two matching passwords ".center(40, "-"))
print(_test(listener="password", client="password"))
print(" client has wrong password ".center(40, "-"))
print(_test(listener="password", client="wrong"))
print(" client has no password ".center(40, "-"))
print(_test(listener="password", client=None))
# This is the case which deadlocks
print(" listener has no password ".center(40, "-"))
print(_test(listener=None, client="password"))
which outputs:
------------- no passwords -------------
(None, None, ['hello'])
-------- two matching passwords --------
(None, None, ['hello'])
------ client has wrong password -------
(AuthenticationError('digest received was wrong'), AuthenticationError('digest sent was rejected'), [])
-------- client has no password --------
(AuthenticationError("expected 'md5' of length 16 got 20"), None, [])
------- listener has no password -------
and then stops.
Upon some investigation, the following bit of code from Client
is to blame:
if authkey is not None:
answer_challenge(c, authkey)
deliver_challenge(c, authkey)
since the listener is not configured to deliver the challenge to the connections. I think this would be resolved with an optional timeout kwarg in answer_challenge
. If this suggestion is accepted I would be very happy to work on it 👍
CPython versions tested on:
3.9, 3.10, 3.11, 3.12
Operating systems tested on:
macOS, Windows
Metadata
Metadata
Assignees
Projects
Status
Todo