Skip to content

fix: release pit->name and pit->modname in _del_pit - #221

Merged
sumerc merged 1 commit into
masterfrom
fix-220
Jul 8, 2026
Merged

fix: release pit->name and pit->modname in _del_pit#221
sumerc merged 1 commit into
masterfrom
fix-220

Conversation

@sumerc

@sumerc sumerc commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Fixes #220

_del_pit() only released pit->fn_descriptor, leaking the owned references in pit->name and pit->modname every time a pit was destroyed (per unique profiled function, per clear_stats() cycle):

  • Python-code path (_code2pit): explicitly Py_INCREF'd co_name / co_filename (or a fresh PyStr_FromFormat for Class.method names)
  • C-function path (_ccode2pit): freshly created strings from PyObject_Repr / PyStr_FromString / _pycfunction_module_name — real memory, not just refcounts

The fix adds the two missing Py_XDECREFs (X because name can legitimately be NULL if its creation failed).

Regression test

test_clear_stats_does_not_leak_pit_name_refs asserts sys.getrefcount on co_name/co_filename stays flat across repeated profile/clear_stats() cycles. Before the fix it fails with exactly +1 ref per cycle on both fields; after, it passes.

One subtlety baked into the test: on CPython 3.12+ compile-interned strings are immortal, so a naive getrefcount on a normal function's co_name can't see the leak (and identifier-like string literals are compile-interned too). The test therefore rebuilds the code object via code.replace() with runtime-built strings, which are mortal and uniquely held — making the assert exact on all supported versions.

Full suite (103 tests) passes on CPython 3.14.3 / macOS arm64.

🤖 Generated with Claude Code

_del_pit() only DECREF'd pit->fn_descriptor, leaking the owned
references held in pit->name and pit->modname every time a pit was
destroyed (e.g. on clear_stats()) — fresh string objects in the
C-function path, INCREF'd co_name/co_filename in the Python path.

Adds a regression test asserting refcounts stay flat across repeated
profile/clear_stats cycles. The test uses runtime-built co_name/
co_filename strings because compile-interned strings are immortal on
3.12+, which would hide the leak from sys.getrefcount.

Fixes #220

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@sumerc
sumerc merged commit c2f6d43 into master Jul 8, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

_del_pit() leaks pit->name and pit->modname

1 participant