Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

`test_is_python_process_non_python_subprocess` always times out when `sleep` is a multicall binary (Alpine/BusyBox, RHEL UBI9)

オープン 初心者向け
#160,881 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
76/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
linux, python

調査の方向性

Lib/test/test_profiling/test_sampling_profiler/test_children.pyを読み、特に_wait_for_process_exec()とtest_is_python_process_non_python_subprocessを確認してください。Issueには、名前に関係なく子プロセスの実行ファイルが変わったことを検出するチェック案が含まれています。ヘルパーとその呼び出し箇所を更新し、Linuxで指定されたテストを実行してください。multicallのsleepバイナリと通常のバイナリの両方でパスするはずです。

索引モデルが issue の本文から書いたものです。

説明

tests topic-profiling type-bug
Bug report
Bug description:

The fix for gh-159534 (GH-160028, backported to 3.15 in GH-160080) makes test_is_python_process_non_python_subprocess fail every time on systems where sleep is provided by a multicall binary. That includes the Alpine buildbots, where the original gh-159534 failure was found:

FAIL: test_is_python_process_non_python_subprocess (test.test_profiling.test_sampling_profiler.test_children.TestIsPythonProcess.test_is_python_process_non_python_subprocess)
Test that a non-Python subprocess is not detected as Python.
----------------------------------------------------------------------
Traceback (most recent call last):
  File ".../Lib/test/test_profiling/test_sampling_profiler/test_children.py", line 628, in test_is_python_process_non_python_subprocess
    _wait_for_process_exec(proc, "sleep", SHORT_TIMEOUT)
  File ".../Lib/test/test_profiling/test_sampling_profiler/test_children.py", line 91, in _wait_for_process_exec
    for _ in sleeping_retry(timeout, max_delay=0.1):
  File ".../Lib/test/support/__init__.py", line 2779, in sleeping_retry
    for _ in busy_retry(timeout, err_msg, error=error):
  File ".../Lib/test/support/__init__.py", line 2749, in busy_retry
    raise AssertionError(msg)
AssertionError: timeout (45.1 seconds)
Buildbots

AMD64 Alpine Linux NoGIL 3.x:

  • build 3444 (before GH-160028): the original intermittent failure, True is not false.
  • build 3445 (first build with GH-160028): timeout (45.1 seconds). Every build since fails the same way, e.g. build 3523.

AMD64 Alpine Linux 3.15:

  • build 800 (before GH-160080): only test_lazy_import fails.
  • build 815 (first build with GH-160080) and every build since, including build 851 just before v3.15.2 was tagged: this test fails too.

This failure is separate from the test_lazy_import crash on Alpine (gh-159535). The Alpine builders will stay red after that crash is fixed.

Cause

The new _wait_for_process_exec() helper waits until os.path.basename(os.readlink(f"/proc/{pid}/exe")) == "sleep". When sleep is a multicall binary, /proc/{pid}/exe points to the multicall binary instead:

System /usr/bin/sleep or /bin/sleep /proc/{pid}/exe of a running sleep
Alpine 3.24 (BusyBox) symlink to /bin/busybox /bin/busybox
RHEL UBI9 (coreutils-single, the image default) shebang script #!/usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/coreutils
RHEL UBI9 after dnf swap coreutils-single coreutils regular binary /usr/bin/sleep

The condition never becomes true, so the test always times out.

Reproducer, tested in python:3-alpine and registry.access.redhat.com/ubi9/ubi:

import os, subprocess, time
proc = subprocess.Popen(["sleep", "10"])
time.sleep(0.5)
print(os.readlink(f"/proc/{proc.pid}/exe"))
proc.kill()
Suggested fix

The helper only needs to know that the child has called exec(). The program name doesn't matter. Before exec(), the forked child's /proc/{pid}/exe is the parent's Python executable, so wait until it differs from the parent's:

-def _wait_for_process_exec(proc, name, timeout):
+def _wait_for_process_exec(proc, timeout):
     # Wait until a child process calls exec() to replace the forked process
-    # executable. Raise AssertionError on timeout.
+    # executable. Don't check the executable name: it can be a multicall
+    # binary such as /bin/busybox. Raise AssertionError on timeout.
+    parent_exe = os.readlink("/proc/self/exe")
     for _ in sleeping_retry(timeout, max_delay=0.1):
         exe = os.readlink(f"/proc/{proc.pid}/exe")
-        if os.path.basename(exe) == name:
+        if exe != parent_exe:
             break
-            _wait_for_process_exec(proc, "sleep", SHORT_TIMEOUT)
+            _wait_for_process_exec(proc, SHORT_TIMEOUT)

I tested this check with the reproducer on Alpine (BusyBox) and on UBI9 with both coreutils-single and coreutils. It detects the exec() in all three cases, while the current name check fails on Alpine and on UBI9 with coreutils-single.

CPython versions tested on:

3.15.2, CPython main branch

Operating systems tested on:

Linux (Alpine 3.24 buildbots, RHEL UBI9 container)

CPython versions tested on:

3.15

Operating systems tested on:

Linux

Linked PRs
  • gh-160901
主要言語
Python
スター
77.8k
フォーク
37.7k
平均マージ
11時間 25分
マージ済み PR(30日)
723

環境構築

Codespaces で開く

このプロジェクトの開発コンテナを、あなたの GitHub アカウントでブラウザ上に起動します。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

python/cpython のほかの issue

python/cpython の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。