From 1cadeb40df15c1eaef3410064f9a2b8e4489082d Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 6 Sep 2016 21:25:57 -0400 Subject: MAINT-5232: Prevent runaway LLSingletonBase::MasterList growth. Until we reimplement LLCoros on Boost.Fiber, we must hand-implement coroutine-local data. That presently takes the form of a map keyed on llcoro::id, whose values are the stacks of currently-initializing LLSingleton instances. But since the viewer launches an open-ended number of coroutines, we could end up with an open-ended number of map entries unless we intentionally prune the map. So every time we pop the stack to empty, remove that map entry. This could result in thrashing, a given coroutine's 'initializing' stack being created and deleted for almost every LLSingleton instantiated by that coroutine -- but the number of different LLSingletons is necessarily static, and the lifespan of each is the entire rest of the process. Even a couple dozen LLSingletons won't thrash that badly. --- indra/llcommon/llsingleton.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'indra/llcommon/llsingleton.cpp') diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp index 3f65820f2e..24ccc8ddb4 100644 --- a/indra/llcommon/llsingleton.cpp +++ b/indra/llcommon/llsingleton.cpp @@ -94,6 +94,15 @@ public: // here. It returns a reference to the selected mapped_type instance. return mInitializing[llcoro::get_id()]; } + + void cleanup_initializing_() + { + InitializingMap::iterator found = mInitializing.find(llcoro::get_id()); + if (found != mInitializing.end()) + { + mInitializing.erase(found); + } + } }; //static @@ -129,7 +138,7 @@ LLSingletonBase::list_t& LLSingletonBase::get_initializing() //static LLSingletonBase::list_t& LLSingletonBase::get_initializing_from(MasterList* master) { - return master->get_initializing_();; + return master->get_initializing_(); } LLSingletonBase::~LLSingletonBase() {} @@ -156,6 +165,17 @@ void LLSingletonBase::pop_initializing() // and pop it list.pop_back(); + // The viewer launches an open-ended number of coroutines. While we don't + // expect most of them to initialize LLSingleton instances, our present + // get_initializing() logic could lead to an open-ended number of map + // entries. So every time we pop the stack back to empty, delete the entry + // entirely. + if (list.empty()) + { + MasterList::instance().cleanup_initializing_(); + } + + // Now validate the newly-popped LLSingleton. if (back != this) { logerrs("Push/pop mismatch in stack of currently-initializing LLSingletons: ", -- cgit v1.2.3