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

Free-threaded Python (3.14t/3.15t): importing _objtrace re-enables the GIL

オープン
#867 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

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

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
39/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
活発
技術スタック
python

調査の方向性

Start with scout_apm/core/objtrace.py and the _objtrace C extension; inspect how the fallback is selected and where the extension declares module slots. Then review .github/workflows/main.yml and the tox environment selection for Python 3.14t and 3.15t. The issue proposes a short term fallback and CI coverage, while making the extension free-threading safe requires investigation and stress tests.

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

説明

Problem

We publish free-threaded wheels (cp314t and cp315t). For example, scout-apm 4.0.0 on PyPI includes scout_apm-4.0.0-cp314-cp314t-*.whl, and cibuildwheel builds cp315t wheels on master. But nothing in CI tests the free-threaded builds, and the _objtrace C extension never declares that it's safe to run without the GIL. It has no Py_mod_gil slot.

So when scout_apm.core.install() imports scout_apm.core._objtrace on a free-threaded interpreter, CPython turns the GIL back on for the whole process:

RuntimeWarning: The global interpreter lock (GIL) has been enabled to load module 'scout_apm.core._objtrace', which has not declared that it can run safely without the GIL. To override this behavior and keep the GIL disabled (at your own risk), run with PYTHON_GIL=0 or -Xgil=0.

The impact:

  • Any free-threaded app with scout-apm installed quietly loses free-threading. sys._is_gil_enabled() becomes True after the import.
  • When warnings are errors (-W error, or our own pytest.ini), the import raises RuntimeWarning. The fallback in objtrace.py only catches ImportError, so the exception isn't handled. A free-threaded CI job would fail on this right away.

Reproduce

uv venv -p 3.15t venv && VIRTUAL_ENV=venv uv pip install "scout-apm @ ."
venv/bin/python -c "import sys; from scout_apm.core import objtrace; print(objtrace.is_extension, sys._is_gil_enabled())"
# RuntimeWarning as above, then: True True

What objtrace provides

objtrace only produces the per-span allocation tags: allocations, start_allocations and stop_allocations (tracked_request.py, add_allocation_tags). Memory increase per request (RSS via psutil) and the memory sampler don't depend on it. The agent already runs without objtrace on PyPy, with SCOUT_DISABLE_EXTENSIONS=1, and whenever the optional extension fails to compile. In those cases add_allocation_tags() just skips the tags.

Proposed plan

  1. Short term: on free-threaded builds, use the existing no-op fallback in objtrace.py instead of importing the extension, for example when sysconfig.get_config_var("Py_GIL_DISABLED") is set. The GIL stays off, and allocation tags are skipped like they are on PyPy.
  2. CI: add 3.14t and 3.15t jobs, with py314t-* and py315t-* tox envs. The env selection in main.yml currently strips the version down to digits (3.15t becomes 315) and matches ^py315 as a prefix, so it would also need to match the t suffix exactly.
  3. Longer term (needs investigation): make _objtrace actually safe without the GIL and declare Py_MOD_GIL_NOT_USED. The counters are already thread-local (__thread). The open questions:
    • enable() and disable() read and write installed without a lock. A concurrent double enable() would wrap our own hook and recurse infinitely.
    • We'd need to confirm whether calling PyMem_SetAllocator at runtime, while other threads are allocating, is safe on free-threaded CPython.
    • Stress tests on 3.14t/3.15t would be needed before shipping.
  4. Docs: say which Python builds and interpreters report allocation counts. Today the docs don't mention objtrace, PyPy or SCOUT_DISABLE_EXTENSIONS at all.

Found while adding Python 3.15 CI in #866.

主要言語
Python
スター
77
フォーク
19
PR マージ指標
30日以内にマージされた PR はありません

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

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

scoutapp/scout_apm_python のほかの issue

scoutapp/scout_apm_python の issue をすべて見る

似ている issue

Python の issue をもっと見る

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

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