Making two delta ensembles refer to each other stack-overflows in ensemble name generation. Reproduced on dev as SEH exception with code 0xc00000fd from a unit test doing nothing but deltaA->setEnsemble1( deltaB ) after deltaB was already sourced from deltaA.
The loop
Name propagation is a cycle that normally terminates only by reaching a fixed point:
RimSummaryEnsemble::updateName ends in caseNameChanged.send() (RimSummaryEnsemble.cpp:320), guarded by if ( m_name == candidateName ) return; at :317.
RimSummaryCaseMainCollection connects that signal to onCaseNameChanged for every ensemble (RimSummaryCaseMainCollection.cpp:337, :466).
onCaseNameChanged (:680) calls RiaSummaryTools::updateSummaryEnsembleNames(), which calls updateEnsembleNames() (:871), which calls updateName() on every ensemble.
The guard at :317 is the only termination condition. For a delta ensemble, nameKeys() (RimDeltaSummaryEnsemble.cpp:229) is built from m_ensemble1->name() and m_ensemble2->name(), so with A sourced from B and B sourced from A each pass feeds the other a longer name and the fixed point is never reached. The duplicate-name suffixing at RimSummaryEnsemble.cpp:304-314 accelerates it — observed names grow like Delta: Delta: <...> (subset-1) - <...> (subset-1) until the stack runs out.
Trigger
RimDeltaSummaryEnsemble::setEnsemble1/setEnsemble2 (:106, :116) call RiaSummaryTools::updateSummaryEnsembleNames() directly, so the overflow happens inside the setter that closes the cycle. calculateValueOptions excludes only this from the source ensemble options, so the second half of a cycle is offered in the UI. RicNewDerivedEnsembleFeature bypasses the setters and assigns the fields directly, which avoids the overflow but still builds the cycle.
Fix
Refuse the assignment when it would make the dependency graph cyclic, in setEnsemble1()/setEnsemble2() and in the options offered by calculateValueOptions. RimSummaryEnsembleTools::wouldCreateDependencyCycle(), added in #14518, answers exactly that question and is already cycle-safe itself.
Independent of #14517 and #14518 — the traversal fixed there terminates on a cycle, this one does not. The regression test DependencyOrder_CycleTerminates added in #14518 closes its cycle by writing the PdmPtrField directly rather than through the setter, specifically to avoid this overflow.
Making two delta ensembles refer to each other stack-overflows in ensemble name generation. Reproduced on
devasSEH exception with code 0xc00000fdfrom a unit test doing nothing butdeltaA->setEnsemble1( deltaB )afterdeltaBwas already sourced fromdeltaA.The loop
Name propagation is a cycle that normally terminates only by reaching a fixed point:
RimSummaryEnsemble::updateNameends incaseNameChanged.send()(RimSummaryEnsemble.cpp:320), guarded byif ( m_name == candidateName ) return;at:317.RimSummaryCaseMainCollectionconnects that signal toonCaseNameChangedfor every ensemble (RimSummaryCaseMainCollection.cpp:337,:466).onCaseNameChanged(:680) callsRiaSummaryTools::updateSummaryEnsembleNames(), which callsupdateEnsembleNames()(:871), which callsupdateName()on every ensemble.The guard at
:317is the only termination condition. For a delta ensemble,nameKeys()(RimDeltaSummaryEnsemble.cpp:229) is built fromm_ensemble1->name()andm_ensemble2->name(), so with A sourced from B and B sourced from A each pass feeds the other a longer name and the fixed point is never reached. The duplicate-name suffixing atRimSummaryEnsemble.cpp:304-314accelerates it — observed names grow likeDelta: Delta: <...> (subset-1) - <...> (subset-1)until the stack runs out.Trigger
RimDeltaSummaryEnsemble::setEnsemble1/setEnsemble2(:106,:116) callRiaSummaryTools::updateSummaryEnsembleNames()directly, so the overflow happens inside the setter that closes the cycle.calculateValueOptionsexcludes onlythisfrom the source ensemble options, so the second half of a cycle is offered in the UI.RicNewDerivedEnsembleFeaturebypasses the setters and assigns the fields directly, which avoids the overflow but still builds the cycle.Fix
Refuse the assignment when it would make the dependency graph cyclic, in
setEnsemble1()/setEnsemble2()and in the options offered bycalculateValueOptions.RimSummaryEnsembleTools::wouldCreateDependencyCycle(), added in #14518, answers exactly that question and is already cycle-safe itself.Independent of #14517 and #14518 — the traversal fixed there terminates on a cycle, this one does not. The regression test
DependencyOrder_CycleTerminatesadded in #14518 closes its cycle by writing thePdmPtrFielddirectly rather than through the setter, specifically to avoid this overflow.