python / python/cpython

`trace` function is cleared after `RecursionError` is fired

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

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

interpreter-core pending type-bug
主要言語
Python
スター
77.2k
フォーク
35.9k
PR マージ指標
PR 指標を取得中

説明

Bug report

Bug description:

I'm using coverage and pytest-cov in CI to measure the line coverage of the unittests. It is achieved by registering a trace function with sys.settrace.

However, after binsecting my unittests, I found that when a RecursionError is raised, the system trace function will be cleared. That will cause a warning emitted by coverage:

~/Projects/cpython/venv/lib/python3.15t/site-packages/coverage/pytracer.py:355: CoverageWarning: Trace function changed, data is likely wrong: None != <bound method PyTracer._trace of <PyTracer at 0x200021dcc20: 2076 data points in 11 files>> (trace-changed)
  self.warn(

Reproducible code:

import sys


def tracer(*args, **kwargs):
    pass


def factorial(n: int) -> int:
    """Calculate the factorial of a number."""
    if n <= 1:
        return 1
    return n * factorial(n - 1)


sys.settrace(tracer)
assert sys.gettrace() is tracer

sys.setrecursionlimit(64)
assert sys.gettrace() is tracer

try:
    _ = factorial(100)
except RecursionError:
    pass

assert sys.gettrace() is None

REPL Output:

# Add a code block here, if required
$ python3                      
Python 3.13.3 (main, Apr  8 2025, 13:54:08) [Clang 16.0.0 (clang-1600.0.26.6)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> def tracer(*args, **kwargs):
...     pass
... 
>>> def factorial(n):
...     if n <= 1:
...         return 1
...     return n * factorial(n - 1)
...     
>>> sys.settrace(tracer)
>>> sys.gettrace() is tracer
True
>>> sys.setrecursionlimit(64)
>>> _ = factorial(100)
Traceback (most recent call last):
  File "<python-input-6>", line 1, in <module>
    _ = factorial(100)
  File "<python-input-2>", line 4, in factorial
    return n * factorial(n - 1)
               ~~~~~~~~^^^^^^^
  File "<python-input-2>", line 4, in factorial
    return n * factorial(n - 1)
               ~~~~~~~~^^^^^^^
  File "<python-input-2>", line 4, in factorial
    return n * factorial(n - 1)
               ~~~~~~~~^^^^^^^
  [Previous line repeated 51 more times]
  File "<python-input-2>", line 1, in factorial
    def factorial(n):
    
RecursionError: maximum recursion depth exceeded
>>> sys.gettrace() is None
True
CPython versions tested on:

CPython main branch

Operating systems tested on:

macOS

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

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

調査の方向性

提供された reproducer を実行し、再帰的な factorial 呼び出し周辺における sys.settrace、sys.gettrace、RecursionError の挙動を調査します。再帰制限の処理と tracing に関係する CPython の実装パスを追跡します。完了の条件は、RecursionError の後も登録された trace 関数が利用可能なままであり、reproducer に対する回帰テストのカバレッジがあることです。

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

評価

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

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

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