Skip to content

Commit 66e6964

Browse files
committed
lazy: detect cyclic instance materialization
Track in-progress instance loads and report recursive references instead of recursing indefinitely through a cyclic Part 21 graph.
1 parent 844a380 commit 66e6964

2 files changed

Lines changed: 28 additions & 0 deletions

File tree

include/cllazyfile/lazyInstMgr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class SC_LAZYFILE_EXPORT lazyInstMgr {
8080
std::map<instanceID, size_t> _pinCounts;
8181
std::set<instanceID> _batchOwnedInstances;
8282
std::set<instanceID> _permanentlyLoadedInstances;
83+
std::set<instanceID> _instancesLoading;
8384
size_t _batchLoadDepth;
8485

8586
LazyProgressCallback _progressCallback;

src/cllazyfile/lazyInstMgr.cc

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,33 @@ SDAI_Application_instance * lazyInstMgr::loadInstance( instanceID id, bool reSee
254254
emitDiagnostic( diagnostic );
255255
return 0;
256256
}
257+
const std::pair<std::set<instanceID>::iterator, bool> loading_result = _instancesLoading.insert( id );
258+
if( !loading_result.second ) {
259+
LazyDiagnostic diagnostic;
260+
diagnostic.severity = LAZY_DIAGNOSTIC_ERROR;
261+
diagnostic.entity = id;
262+
const char * type = typeFromFile( id );
263+
if( type ) diagnostic.type = type;
264+
instanceStreamPos_t::cvector * positions = _instanceStreamPos.find( id );
265+
if( positions && !positions->empty() ) {
266+
diagnostic.offset = positions->front().begin;
267+
}
268+
diagnostic.message = "cyclic dependency encountered while materializing instance";
269+
emitDiagnostic( diagnostic );
270+
return 0;
271+
}
272+
/* sectionReader materializes referenced instances recursively. Keep an
273+
* explicit in-progress set because an instance is not cacheable until its
274+
* STEPread() has completed. */
275+
class LoadingGuard {
276+
public:
277+
LoadingGuard( std::set<instanceID> & loading, instanceID id )
278+
: _loading( loading ), _id( id ) {}
279+
~LoadingGuard() { _loading.erase( _id ); }
280+
private:
281+
std::set<instanceID> & _loading;
282+
instanceID _id;
283+
} loading_guard( _instancesLoading, id );
257284
instanceStreamPos_t::cvector * cv;
258285
if( 0 != ( cv = _instanceStreamPos.find( id ) ) ) {
259286
switch( cv->size() ) {

0 commit comments

Comments
 (0)