Conversation
_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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #220
_del_pit()only releasedpit->fn_descriptor, leaking the owned references inpit->nameandpit->modnameevery time a pit was destroyed (per unique profiled function, perclear_stats()cycle):_code2pit): explicitlyPy_INCREF'dco_name/co_filename(or a freshPyStr_FromFormatforClass.methodnames)_ccode2pit): freshly created strings fromPyObject_Repr/PyStr_FromString/_pycfunction_module_name— real memory, not just refcountsThe fix adds the two missing
Py_XDECREFs (Xbecausenamecan legitimately be NULL if its creation failed).Regression test
test_clear_stats_does_not_leak_pit_name_refsassertssys.getrefcountonco_name/co_filenamestays 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
getrefcounton a normal function'sco_namecan't see the leak (and identifier-like string literals are compile-interned too). The test therefore rebuilds the code object viacode.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