asyncio.subprocess spawning can block
まだ誰も着手していません。
- 主要言語
- Python
- スター
- 77.2k
- フォーク
- 35.9k
- PR マージ指標
- PR 指標を取得中
説明
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
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
Lib/asyncio/unix_events.py の _make_subprocess_transport() から Lib/asyncio/base_subprocess.py と Lib/subprocess.py の subprocess.Popen() を経由する呼び出し経路を追跡してください。先に進む前に、リンクされている gh-154111 の作業を確認してください。完了時には、subprocess の起動によってイベントループがブロックされないようにし、報告された動作に対する回帰テストのカバレッジを含める必要があります。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- python
- 領域
- operating-systems
- issue の種類
- バグ
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 活発さ
- 停滞
- 明瞭さ
- 説明が足りない
- 初心者へのやさしさ
- 30/100