GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — PyRefTracer_DESTROY is not called for objects deferred by the trashcan mechanism · Issue #156371 · python/cpython

PyRefTracer_DESTROY is not called for objects deferred by the trashcan mechanism #156371

New issue
Copy link
New issue
Copy link
Closed
Closed
PyRefTracer_DESTROY is not called for objects deferred by the trashcan mechanism#156371
Copy link
Assignees
corona10
Labels
3.14bugs and security fixesbugs and security fixes3.15bugs and security fixesbugs and security fixes3.16new features, bugs and security fixesnew features, bugs and security fixestype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Description

@corona10
corona10
opened on Aug 25, 2026
Issue body actions

Bug report

This works correctly until Python 3.13, but #132280 introduces a regression.
A simple PR will fix this issue, and I have already prepared a fix for this issue.

import os
import subprocess
import sys
import sysconfig
import tempfile

CSRC = r"""
#include <Python.h>

static Py_ssize_t list_destroys = 0;

static int
tracer(PyObject *obj, PyRefTracerEvent event, void *data)
{
    if (event == PyRefTracer_DESTROY && PyList_CheckExact(obj)) {
        list_destroys++;
    }
    return 0;
}

static PyObject *
start(PyObject *self, PyObject *args)
{
    list_destroys = 0;
    if (PyRefTracer_SetTracer(tracer, NULL) < 0) {
        return NULL;
    }
    Py_RETURN_NONE;
}

static PyObject *
stop(PyObject *self, PyObject *args)
{
    if (PyRefTracer_SetTracer(NULL, NULL) < 0) {
        return NULL;
    }
    return PyLong_FromSsize_t(list_destroys);
}

static PyMethodDef methods[] = {
    {"start", start, METH_NOARGS, NULL},
    {"stop", stop, METH_NOARGS, NULL},
    {NULL, NULL, 0, NULL},
};

static PyModuleDef_Slot slots[] = {
#ifdef Py_GIL_DISABLED
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
#endif
    {0, NULL},
};

static struct PyModuleDef module = {
    PyModuleDef_HEAD_INIT,
    .m_name = "reftrace_repro",
    .m_size = 0,
    .m_methods = methods,
    .m_slots = slots,
};

PyMODINIT_FUNC
PyInit_reftrace_repro(void)
{
    return PyModuleDef_Init(&module);
}
"""


def build_module():
    tmpdir = tempfile.mkdtemp(prefix="reftrace_repro_")
    src = os.path.join(tmpdir, "reftrace_repro.c")
    with open(src, "w") as f:
        f.write(CSRC)
    ext = os.path.join(tmpdir, "reftrace_repro.so")
    cmd = ["cc", "-O2", "-shared", "-fPIC",
           "-I", sysconfig.get_path("include"),
           "-I", sysconfig.get_path("platinclude"),
           "-o", ext, src]
    if sys.platform == "darwin":
        cmd.insert(3, "-undefined")
        cmd.insert(4, "dynamic_lookup")
    subprocess.run(cmd, check=True)
    sys.path.insert(0, tmpdir)


def run(depth):
    import reftrace_repro

    chain = None
    for _ in range(depth):
        chain = [chain]
    reftrace_repro.start()
    del chain
    destroys = reftrace_repro.stop()
    missing = depth - destroys
    print(f"depth={depth:>7}  DESTROY events={destroys:>7}  "
          f"missing={missing:>5}  [{'BUG' if missing else 'OK'}]")


if __name__ == "__main__":
    print(sys.version)
    build_module()
    run(100)        
    run(200_000)

Status

$ python3.13 repro.py
3.13.11 (main, Dec 17 2025, 20:55:16) [Clang 21.1.4 ]
depth=    100  DESTROY events=    100  missing=    0  [OK]
depth= 200000  DESTROY events= 200000  missing=    0  [OK]

$ python3.14 repro.py
3.14.3 (main, Feb  3 2026, 15:32:20) [Clang 17.0.0 (clang-1700.6.3.2)]
depth=    100  DESTROY events=    100  missing=    0  [OK]
depth= 200000  DESTROY events= 199923  missing=   77  [BUG]

$ python3.15 repro.py
3.15.0a3 (main, Dec 17 2025, 21:18:28) [Clang 21.1.4 ]
depth=    100  DESTROY events=    100  missing=    0  [OK]
depth= 200000  DESTROY events= 199570  missing=  430  [BUG]

$ ./python.exe repro.py   # main (unpatched)
3.16.0a0 (heads/main:e4b22adf249, Aug 26 2026, 01:02:19) [Clang 21.0.0]
depth=    100  DESTROY events=    100  missing=    0  [OK]
depth= 200000  DESTROY events= 199923  missing=   77  [BUG]

Linked PRs

  • gh-156371: Fix missing PyRefTracer_DESTROY events for trashcan objects #156372
  • [3.15] gh-156371: Fix missing PyRefTracer_DESTROY events for trashcan objects (gh-156372) #156789
  • [3.14] gh-156371: Fix missing PyRefTracer_DESTROY events for trashcan objects (gh-156372) #156802

Activity

  1. corona10
    self-assigned this
    on Aug 25, 2026
  2. corona10
    added
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    3.14bugs and security fixesbugs and security fixes
    3.15bugs and security fixesbugs and security fixes
    3.16new features, bugs and security fixesnew features, bugs and security fixes
    on Aug 25, 2026
  3. markshannon commented on Aug 26, 2026

    @markshannon
    markshannon
    on Aug 26, 2026
    Member
    More actions

    OOI, how did you find this issue?

  4. corona10 commented on Aug 26, 2026

    @corona10
    corona10
    on Aug 26, 2026
    MemberAuthor
    More actions

    OOI, how did you find this issue?

    While investigating other issues with Claude Code, I came across this issue. :)
    To clarify, I independently validated the regression and the analysis, and I also directed the proposed solution myself, so this is not AI-generated slop.

  5. corona10
    added 5 commits that reference this issue on Aug 26, 2026

    Merge branch 'main' into pythongh-156371

    fd3cb74

    Merge remote-tracking branch 'origin/pythongh-156371' into pythongh-1…

    a1ee6d1

    Merge remote-tracking branch 'upstream/main' into pythongh-156371

    3a23485

    gh-156371: Fix missing PyRefTracer_DESTROY events for trashcan objects (

    3dfa574

    [3.14] gh-156371: Fix missing PyRefTracer_DESTROY events for trashcan…

    f6842dd
  6. clin1234
    added a commit that references this issue on Sep 12, 2026

    pythongh-156371: Fix missing PyRefTracer_DESTROY events for trashcan …

    d7ee592
  7. corona10
    added a commit that references this issue on Sep 30, 2026

    pythongh-156371: Fix missing PyRefTracer_DESTROY events for trashcan …

    2844af0
  8. corona10
    added a commit that references this issue on Oct 10, 2026

    [3.15] gh-156371: Fix missing PyRefTracer_DESTROY events for trashcan…

    d575000
  9. corona10
    closed this as completedon Oct 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

  • @corona10
    corona10

Labels

3.14bugs and security fixesbugs and security fixes3.15bugs and security fixesbugs and security fixes3.16new features, bugs and security fixesnew features, bugs and security fixestype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    You are visitor 01402503 — GeezerVison does not store the pages you look up.
    Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.