Hacktoberfest 2026: as issues que os mantenedores marcaram para outubro, abertas e boas para iniciantes. Ver issues do Hacktoberfest

test_forkserver_sigkill: join() can return before the child sets the event

Fechada Para iniciantes
#160,295 0 comentários 0 reações 0 responsáveis Ver no GitHub

Mantenedores costumam responder em até 1 dia

Ninguém assumiu esta issue ainda.

Avaliação

Dificuldade
2/5
Tempo estimado
1-3 horas
Facilidade para iniciantes
71/100
Tipo de issue
Bug
Clareza
Claramente especificada
Status de atividade
Ativa
Stack de tecnologia
python
Domínio
testing

Direção de pesquisa

Leia Lib/test/_test_multiprocessing.py, especialmente check_forkserver_death() e test_forkserver_sigkill; a falha é que join() pode retornar antes que o processo filho defina o evento depois que o forkserver é encerrado. Atualize a verificação do evento para aguardar com um timeout e, em seguida, execute o teste específico do forkserver. O trabalho estará concluído quando o teste der tempo para o processo filho definir o evento e continuar verificando o código de saída esperado.

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

Descrição

tests topic-multiprocessing type-bug

Bug report

Bug description:

test_forkserver_sigkill failed once during a full ./python.exe -m test -j0 run on my machine (macOS 27.0.1, Apple M3, pydebug build of main at 1705e512b30). The load average was around 65 at the time. It passes when run on its own.

test test.test_multiprocessing_forkserver.test_processes failed -- Traceback (most recent call last):
  File "Lib/test/_test_multiprocessing.py", line 1007, in test_forkserver_sigkill
    self.check_forkserver_death(signal.SIGKILL)
  File "Lib/test/_test_multiprocessing.py", line 997, in check_forkserver_death
    self.assertTrue(evt.is_set())
AssertionError: False is not true

(paths shortened)

This is the same failure as gh-78221 (bpo-34040). It was worked around in 2018 by shortening the child's delay relative to the parent's sleep (07888e1cce), but the race is still there.

check_forkserver_death() kills the forkserver right after starting the first process. After a SIGKILL, the forkserver can no longer report that child's exit status: proc.join() gets EOF on the status pipe, and Popen.poll() in Lib/multiprocessing/popen_forkserver.py sets returncode to 255 immediately. The child may still be running at that point. The test then checks evt.is_set(), which only passes if the child has set the event by then (within the 1 second sleep plus the time proc2 takes). The next line already accepts exit code 255 for the case where the forkserver was killed.

SIGINT is not affected: the forkserver ignores it, stays alive and reports the real exit code.

To reproduce it reliably, stop the first child with SIGSTOP for a few seconds after killing the forkserver:

Reproducer
import multiprocessing as mp, os, signal, threading, time
from multiprocessing.forkserver import _forkserver

def sleep_and_set(evt, delay=0.0):
    time.sleep(delay)
    evt.set()

if __name__ == '__main__':
    mp.set_start_method('forkserver')
    _forkserver.ensure_running()
    evt = mp.Event()
    proc = mp.Process(target=sleep_and_set, args=(evt, 0.5))
    proc.start()
    os.kill(_forkserver._forkserver_pid, signal.SIGKILL)
    # Simulate the child not getting CPU time for 3 seconds.
    os.kill(proc.pid, signal.SIGSTOP)
    threading.Timer(3.0, os.kill, (proc.pid, signal.SIGCONT)).start()
    time.sleep(1.0)
    proc.join()
    print(proc.exitcode, evt.is_set())  # 255 False
    print(evt.wait(60))                 # True: the child did run, later

Waiting for the event with a timeout, instead of checking it right after join(), fixes it.

The same code is in 3.13, 3.14 and 3.15.

CPython versions tested on:

CPython main branch

Operating systems tested on:

macOS, Linux

Linked PRs
  • gh-160296
Linguagem predominante
Python
Estrelas
77.7k
Forks
38.3k
Merge médio
11h 58min
PRs com merge (30d)
672

Preparar o ambiente

Abrir no Codespaces

Inicia o contêiner de desenvolvimento do projeto no navegador, com a sua própria conta do GitHub.

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.

Mais de python/cpython

Todas as issues de python/cpython

Issues semelhantes

Mais issues de Python

Receba novas issues na sua caixa de entrada

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