test_forkserver_sigkill: join() can return before the child sets the event
Maintainer antworten meist innerhalb von 1 Tag
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 2/5
- Geschätzter Aufwand
- 1-3 Stunden
- Anfängerfreundlichkeit
- 71/100
Rechercherichtung
Lies Lib/test/_test_multiprocessing.py, insbesondere check_forkserver_death() und test_forkserver_sigkill; der Fehler besteht darin, dass join() zurückkehren kann, bevor der Child-Prozess das Event setzt, nachdem der Forkserver beendet wurde. Aktualisiere die Event-Prüfung so, dass sie mit einem Timeout wartet, und führe anschließend den gezielten Forkserver-Test aus. Fertig ist die Änderung, wenn der Test dem Child-Prozess Zeit gibt, das Event zu setzen, und weiterhin den erwarteten Exit-Code prüft.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
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
- Vorherrschende Sprache
- Python
- Sterne
- 77.7k
- Forks
- 38.3k
- Ø Merge
- 12 Std. 27 Min.
- Gemergte PRs (30 T.)
- 645
Entwicklungsumgebung
Startet den Dev-Container des Projekts im Browser, mit Ihrem eigenen GitHub-Konto.
- Kein Dockerfile und keine Docker-Compose-Datei
- Hat eine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus python/cpython
-
tests topic-profiling type-bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
Maintainer antworten meist innerhalb von 1 Tag
-
extension-modules type-bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 84/100
Maintainer antworten meist innerhalb von 1 Tag
-
interpreter-core type-feature
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 78/100
python/cpython#160109 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 1 Tag
-
extension-modules type-bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 72/100
python/cpython#160001 · 3 Kommentare ·
Maintainer antworten meist innerhalb von 1 Tag
-
stdlib topic-XML type-bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 76/100
Maintainer antworten meist innerhalb von 1 Tag
Ähnliche Issues
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 77/100
khuisman/mcp-gee-sweet#1166 ·
Maintainer antworten meist innerhalb von 1 Tag
-
bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 70/100
lugassawan/swe-workbench#823 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 85/100
gramaziokohler/compas_timber#870 ·
-
security-scan-failure
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
semantica-agi/semantica#2089 ·
Maintainer antworten meist innerhalb von 1 Tag
-
bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 82/100
autowarefoundation/autoware_carla_scenario#500 ·
Maintainer antworten meist innerhalb von 1 Tag