asyncio.subprocess spawning can block
Personne n'a encore pris cette issue.
- Langage dominant
- Python
- Étoiles
- 77.2k
- Forks
- 35.9k
- Métriques de merge des PR
- Métriques de PR en attente
Description
Bug report
Bug description:
asyncio.create_subprocess_exec() and asyncio.create_subprocess_shell() call subprocess.Popen() synchronously on the event loop thread. Popen._execute_child() performs a blocking os.read() on a CLOEXEC error pipe (Lib/subprocess.py, current main line 1995) that doesn't return until the child completes execve(). This blocks the event loop for the duration of:
fork()/posix_spawn()— page-table duplication proportional to parent process size- Child-side setup (signal disposition, fd operations,
chdir, uid/gid changes) execve()— kernel loads the binary, maps pages before applying O_CLOEXEC
The call chain on the event loop thread is:
_make_subprocess_transport() [async — Lib/asyncio/unix_events.py:197]
→ _UnixSubprocessTransport.__init__() [sync]
→ BaseSubprocessTransport.__init__() [sync — Lib/asyncio/base_subprocess.py:40]
→ self._start() [sync]
→ subprocess.Popen() [sync]
→ _execute_child() [sync — Lib/subprocess.py:1878]
→ os.read(errpipe_read, 50000) [BLOCKS — line 1995]
In production, we have observed this blocking the event loop for multiple seconds when a Python process spawns a large binary (with a substantial statically-linked dependency set) on a system that was within operational parameters for memory usage (no ongoing swapping or similar) but subject to IO read contention slowing the binary-loading process.
The original python/asyncio#414 identified this in 2016; the asyncio repo was archived without resolution or migration to cpython's tracker.
#81444 would serve to fix this issue (by having asyncio.subprocess dispatch to a thread). However, I'm not sure it constitutes the only fix, or even an ideal fix — we should be able to watch for the FIFO either closing or having data available to read using natively asynchronous syscalls.
Observed in production on Python 3.13; determination that the issue still exists in 3.14 and current main based on source tree inspection.
CPython versions tested on:
3.13
Operating systems tested on:
Linux
Linked PRs
- gh-154111
Guide de contribution
Ouvrir le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Piste de recherche
Suivez le chemin d’appel depuis _make_subprocess_transport() dans Lib/asyncio/unix_events.py, en passant par Lib/asyncio/base_subprocess.py et subprocess.Popen() dans Lib/subprocess.py. Examinez le travail lié à gh-154111 avant de poursuivre ; la réalisation devrait empêcher le démarrage de subprocess de bloquer la boucle d’événements et inclure une couverture de régression pour le comportement signalé.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- python
- Domaine
- operating-systems
- Type d'issue
- Bug
- Difficulté
- 5/5
- Temps estimé
- Plus d'une semaine
- Activité
- À l'abandon
- Clarté
- À clarifier
- Accessibilité débutants
- 30/100