mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-27 15:41:00 -05:00
#14423 Defer destruction of orphaned derived cases to a batch flush
Closing all summary cases while a delta ensemble is present crashed with a use-after-free. RicCloseSummaryCaseFeature::deleteSummaryCases holds a case list across removeCases and deletes it afterwards, while removeCases made the delta ensemble rebuild and destroy derived cases that are themselves part of that list. The previous fix rewrote the caller list with the surviving cases, which stopped the crash but left the hazard in place for any other caller holding a case list across a removal. Add RimSummaryCaseUpdateBatch, a plain scope object that is ambient for the duration of its scope. Removal now only detaches, and hands the detached cases to the batch. The outermost scope flushes, regenerating the dirty delta ensembles in dependency order first so a chained delta ensemble sees the final state of its source, then destroying the orphans with caf::PdmObjectHandleTools::deleteObjects. A nested batch contributes to the outermost one and never flushes. Orphans are held as guarded pointers, so a case the caller destroyed itself is skipped instead of being destroyed twice. Both contribution points fall back to immediate execution when no batch is active, so call sites that do not open one keep behaving as before. Open a batch in RimSummaryCaseMainCollection::removeCases and in RicCloseSummaryCaseFeature::deleteSummaryCases, which is the outermost of the two and therefore keeps the detached cases alive across its own deleteObjects call. removeCases no longer rewrites the caller list, so it now takes it by const reference.
This commit is contained in:
1 parent
6c0cc9c363
commit
8ac2255832
9 files changed
+334
-43
No files matched your search
@@ -48,6 +48,7 @@
|
||||
#include "RimProject.h"
|
||||
#include "RimRftPlotCollection.h"
|
||||
#include "RimSummaryCase.h"
|
||||
#include "RimSummaryCaseUpdateBatch.h"
|
||||
#include "RimSummaryCurve.h"
|
||||
#include "RimSummaryEnsemble.h"
|
||||
#include "RimSummaryMultiPlotCollection.h"
|
||||
@@ -227,16 +228,16 @@ void RimSummaryCaseMainCollection::removeCase( RimSummaryCase* summaryCase, bool
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSummaryCaseMainCollection::removeCases( std::vector<RimSummaryCase*>& cases )
|
||||
void RimSummaryCaseMainCollection::removeCases( const std::vector<RimSummaryCase*>& cases )
|
||||
{
|
||||
// Removing one case can delete other cases in the list. A delta ensemble recreates its derived cases when a source
|
||||
// case is removed, and deletes the derived cases no longer in use. Use guarded pointers to avoid touching deleted
|
||||
// cases, and return only the cases that are still alive.
|
||||
std::vector<caf::PdmPointer<RimSummaryCase>> guardedCases( cases.begin(), cases.end() );
|
||||
// Removing one case makes a delta ensemble rebuild its derived cases, and some of those derived cases can be part
|
||||
// of this very list. The batch detaches them now and destroys them when the outermost batch scope ends, so a caller
|
||||
// holding on to the list across this call never sees a freed case, as long as it opens a batch of its own.
|
||||
RimSummaryCaseUpdateBatch updateBatch;
|
||||
|
||||
for ( const auto& sumCase : guardedCases )
|
||||
for ( auto sumCase : cases )
|
||||
{
|
||||
if ( sumCase.notNull() ) removeCase( sumCase, false );
|
||||
removeCase( sumCase, false );
|
||||
}
|
||||
|
||||
for ( RimSummaryEnsemble* ensemble : m_ensembles )
|
||||
@@ -244,12 +245,6 @@ void RimSummaryCaseMainCollection::removeCases( std::vector<RimSummaryCase*>& ca
|
||||
ensemble->updateReferringCurveSetsZoomAll();
|
||||
}
|
||||
|
||||
cases.clear();
|
||||
for ( const auto& sumCase : guardedCases )
|
||||
{
|
||||
if ( sumCase.notNull() ) cases.push_back( sumCase );
|
||||
}
|
||||
|
||||
dataSourceHasChanged.send();
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user