multiprocessing.connection.Client deadlocks when trying to connect to a listener without a password
まだ誰も着手していません。
- 主要言語
- Python
- スター
- 77.2k
- フォーク
- 35.9k
- PR マージ指標
- PR 指標を取得中
説明
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
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
multiprocessing.connection.Client と、レポートで特定された answer_challenge パスから始め、その後、提供された reproducer を認証の組み合わせ全体に対して実行します。listener-without-password と client-with-password のケースでハングしなくなり、その他の報告されたケースでは実証された結果が維持されれば完了です。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- python
- 領域
- distributed-systems, networking
- issue の種類
- バグ
- 難易度
- 3/5
- 見積もり時間
- 1〜2日
- 活発さ
- 停滞
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 45/100