python / python/cpython

multiprocessing.connection.Client deadlocks when trying to connect to a listener without a password

Aberta
#123,736 6 comentários 0 reações 0 responsáveis Ver no GitHub

Ninguém assumiu esta issue ainda.

stdlib topic-multiprocessing type-bug
Linguagem predominante
Python
Estrelas
77.2k
Forks
35.9k
Métricas de merge de PRs
Métricas de PR pendentes

Descrição

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

Guia de contribuição

Abrir o guia de contribuição

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Direção de pesquisa

Comece com multiprocessing.connection.Client e o caminho answer_challenge identificado no relatório; em seguida, execute o reproducer fornecido com todas as suas combinações de autenticação. Está concluído quando o caso listener-without-password e client-with-password não travar mais, enquanto os outros casos relatados mantiverem os resultados demonstrados.

Escrita pelo modelo de indexação a partir do texto da issue.

Avaliação

Stack de tecnologia
python
Domínio
distributed-systems, networking
Tipo de issue
Bug
Dificuldade
3/5
Tempo estimado
1-2 dias
Status de atividade
Estagnada
Clareza
Razoavelmente clara
Facilidade para iniciantes
45/100

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.