Skip to content

[cppjit] Fix leaked container reference in vector_iter [upstream] - #23672

Open
guitargeek wants to merge 1 commit into
root-project:masterfrom
guitargeek:cppjit-vector-iter-leak
Open

guitargeek wants to merge 1 commit into
root-project:masterfrom
guitargeek:cppjit-vector-iter-leak

Conversation

@guitargeek

Copy link
Copy Markdown
Contributor

vector_iter() took two references to the container, one when storing it and one after deciding whether the container is a temporary, while the iterator's dealloc releases only one. Every iteration over a std::vector proxy therefore leaked a reference to it: the proxy, and the C++ object if Python owns it, never got freed.

ROOT's own cppyy copy got this right in #19017 (commit 700fee6), which moved the temporary check before the increment so that PyUnstable_Object_IsUniqueReferencedTemporary() sees the untouched refcount on Python 3.14, and dropped the original increment. The port of that change to the compiler-research fork,
compiler-research/CPyCppyy#151 (commit 8eba11b58c, reapplied as 7e086216a3), added the new increment after the check but kept the original one. cppjit inherited both in its initial import (compiler-research/cppjit@38b22b99be), and ROOT with the vendoring in 552d291. Upstream cppjit still has both.

Beyond the memory, the leak made pyroot-pyz-ttree-branch flaky: the proxies leaked by the earlier read test stayed registered in the memory regulator under addresses the closed file had freed, so when a later new std::vector<double> landed on one of them, reading the pointer data member returned the stale proxy instead of a reference proxy, and TTree::Branch() got bound to the proxy's own pointer slot.

🤖 Done with the help of AI

@guitargeek
guitargeek requested a review from aaronj0 as a code owner October 9, 2026 16:16
@guitargeek guitargeek changed the title [cppjit] Fix leaked container reference in vector_iter [ROOT-patch] [cppjit] Fix leaked container reference in vector_iter [upstream] Oct 9, 2026
vector_iter() took two references to the container, one when storing it
and one after deciding whether the container is a temporary, while the
iterator's dealloc releases only one. Every iteration over a std::vector
proxy therefore leaked a reference to it: the proxy, and the C++ object
if Python owns it, never got freed.

ROOT's own cppyy copy got this right in root-project#19017 (commit
700fee6), which moved the temporary check before the increment so
that PyUnstable_Object_IsUniqueReferencedTemporary() sees the untouched
refcount on Python 3.14, and dropped the original increment. The port of
that change to the compiler-research fork,
compiler-research/CPyCppyy#151 (commit 8eba11b58c, reapplied as
7e086216a3), added the new increment after the check but kept the
original one. cppjit inherited both in its initial import
(compiler-research/cppjit@38b22b99be), and ROOT with the vendoring in
552d291. Upstream cppjit still has both.

Beyond the memory, the leak made pyroot-pyz-ttree-branch flaky: the
proxies leaked by the earlier read test stayed registered in the memory
regulator under addresses the closed file had freed, so when a later
`new std::vector<double>` landed on one of them, reading the pointer
data member returned the stale proxy instead of a reference proxy, and
TTree::Branch() got bound to the proxy's own pointer slot.

🤖 Done with the help of AI
@guitargeek
guitargeek force-pushed the cppjit-vector-iter-leak branch from 7b38fb6 to 6c74d67 Compare October 9, 2026 16:16
@dpiparo dpiparo assigned guitargeek and unassigned aaronj0 Oct 9, 2026
@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

Test Results

    23 files      23 suites   3d 18h 26m 59s ⏱️
 3 882 tests  3 881 ✅ 0 💤 1 ❌
79 605 runs  79 604 ✅ 0 💤 1 ❌

For more details on these failures, see this check.

Results for commit 6c74d67.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants