python / python/cpython

multiprocessing.Process cannot be closed if the process is reaped elsewhere

Aberta
#94,661 1 comentário 0 reações 0 responsáveis Ver no GitHub

Ninguém assumiu esta issue ainda.

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

Descrição

Here's a small reproducer where I start a multiprocessing.Process - then reap it with os.waitpid(

import os
import multiprocessing
import socket
import sys


ctx = multiprocessing.get_context("spawn")

def target(sock):
    with sock:
        sock.send(b"\x00")
        sock.recv(1)


def main():
    a, b = socket.socketpair()
    with a, b:
        with b:
            proc = ctx.Process(target=target, args=(b, ))
            proc.start()
        assert a.recv(1) == b"\x00"
        a.send(b"\x00")
        os.waitpid(proc.pid, 0)
        if sys.version_info >= (3, 7):
            proc.close()
        elif proc.is_alive():
            raise RuntimeError("proc={proc} is still running".format(proc=proc))


if __name__ == "__main__":
    sys.exit(main())

which results in:

 Traceback (most recent call last):
  File "/home/graingert/projects/distributed/demo.py", line 31, in <module>
    sys.exit(main())
  File "/home/graingert/projects/distributed/demo.py", line 25, in main
    proc.close()
  File "/home/graingert/miniconda3/lib/python3.9/multiprocessing/process.py", line 181, in close
    raise ValueError("Cannot close a process while it is still running. "
ValueError: Cannot close a process while it is still running. You should first call join() or terminate().

One issue is the call to self._popen.poll() suppresses the OSError of a reaped process:
https://github.com/python/cpython/blob/b6558d768f19584ad724be23030603280f9e6361/Lib/multiprocessing/popen_fork.py#L26-L31

I think this can be fixed by checking the state of the multiprocessing.Process.sentinel instead of using os.waitpid

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 pelo reproducer da issue e inspecione Lib/multiprocessing/popen_fork.py, especialmente o tratamento de _popen.poll(), juntamente com multiprocessing.Process.close(). Investigue como um processo reaped externamente é representado pelo seu sentinel e compare isso com a detecção de estado baseada em waitpid. Está concluído quando o reproducer puder fazer o reaping externo do processo filho e depois fechar Process sem o ValueError incorreto de que ele ainda está em execução.

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

Avaliação

Stack de tecnologia
python
Domínio
operating-systems
Tipo de issue
Bug
Dificuldade
4/5
Tempo estimado
3-5 dias
Status de atividade
Estagnada
Clareza
Razoavelmente clara
Facilidade para iniciantes
35/100

Receba novas issues na sua caixa de entrada

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