Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

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

Chiusa Adatta ai principianti
#160,295 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
71/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
python
Ambito
testing

Direzione di ricerca

Leggi Lib/test/_test_multiprocessing.py, in particolare check_forkserver_death() e test_forkserver_sigkill; il problema è che join() può restituire prima che il processo figlio imposti l’evento dopo la terminazione del forkserver. Aggiorna il controllo dell’evento in modo che attenda con un timeout, quindi esegui il test mirato del forkserver. Il lavoro è completato quando il test dà al processo figlio il tempo di impostare l’evento e continua a verificare il codice di uscita previsto.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

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
Lingua principale
Python
Stelle
77.7k
Fork
38.3k
Merge medio
12h 27m
PR unite (30g)
710

Preparare l'ambiente

Apri in Codespaces

Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di python/cpython

Tutte le issue di python/cpython

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.