Skip to content

[RF] Delete fit objects before plotting in rf619_discrete_profiling.py#22830

Merged
guitargeek merged 1 commit into
root-project:masterfrom
guitargeek:rf_tutorial
Jul 16, 2026
Merged

[RF] Delete fit objects before plotting in rf619_discrete_profiling.py#22830
guitargeek merged 1 commit into
root-project:masterfrom
guitargeek:rf_tutorial

Conversation

@guitargeek

Copy link
Copy Markdown
Contributor

The Python version of this tutorial sporadically crashes on CI (and deterministically in some local invocations) with memory corruption that is detected in cling's JIT at interpreter shutdown, e.g. as "StringMapImpl::RemoveKey(): Didn't find key?" on builds with LLVM assertions, or as a segfault in llvm::Module::dropAllReferences() / MDNode::dropAllReferences() during ~TCling.

Watchpoint forensics show recycled heap blocks that end up shared between the NLL evaluation machinery (RooFit::Evaluator data-token bookkeeping on the compiled model clones) and IR objects of modules that cling JITs during the plotting phase, with the final stale write coming from RooFit::Evaluator::~Evaluator() at interpreter shutdown.

Deleting the minimizer and the NLL right after the fits closes that window: the evaluator and the owned graph clones are torn down at a well-defined point before the plotting phase compiles new wrappers, and not during the less controlled interpreter shutdown. With this change the previously reproducible crash (8/8 failing runs in a bare invocation) disappears (8/8 + 3/3 ctest passing).

This is a workaround at the tutorial level; the underlying overlapping heap ownership deserves a separate AddressSanitizer investigation.

The Python version of this tutorial sporadically crashes on CI (and
deterministically in some local invocations) with memory corruption that
is detected in cling's JIT at interpreter shutdown, e.g. as
"StringMapImpl::RemoveKey(): Didn't find key?" on builds with LLVM
assertions, or as a segfault in llvm::Module::dropAllReferences() /
MDNode::dropAllReferences() during ~TCling.

Watchpoint forensics show recycled heap blocks that end up shared between
the NLL evaluation machinery (RooFit::Evaluator data-token bookkeeping on
the compiled model clones) and IR objects of modules that cling JITs
during the plotting phase, with the final stale write coming from
RooFit::Evaluator::~Evaluator() at interpreter shutdown.

Deleting the minimizer and the NLL right after the fits closes that
window: the evaluator and the owned graph clones are torn down at a
well-defined point before the plotting phase compiles new wrappers, and
not during the less controlled interpreter shutdown. With this change the
previously reproducible crash (8/8 failing runs in a bare invocation)
disappears (8/8 + 3/3 ctest passing).

This is a workaround at the tutorial level; the underlying overlapping
heap ownership deserves a separate AddressSanitizer investigation.
@guitargeek guitargeek self-assigned this Jul 16, 2026
@guitargeek
guitargeek requested review from couet and dpiparo as code owners July 16, 2026 08:27
@guitargeek
guitargeek merged commit 49fb353 into root-project:master Jul 16, 2026
36 checks passed
@guitargeek
guitargeek deleted the rf_tutorial branch July 16, 2026 11:04
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.

2 participants