From ecdd676e7280a0e64ba96bb6b0d2ced98e094c20 Mon Sep 17 00:00:00 2001 From: Nicky Date: Thu, 3 Nov 2011 15:41:17 +0100 Subject: [PATCH] FIRE-3801; Crash on AO import; Do not delete AOSets during timer events. --- indra/newview/ao.cpp | 2 +- indra/newview/aoengine.cpp | 33 +++++++++++++++++++++++---------- indra/newview/aoengine.h | 8 +++++--- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/indra/newview/ao.cpp b/indra/newview/ao.cpp index ed9b8b4e3e..f709079fde 100644 --- a/indra/newview/ao.cpp +++ b/indra/newview/ao.cpp @@ -424,7 +424,7 @@ void FloaterAO::onClickReload() mSelectedSet=0; mSelectedState=0; - AOEngine::instance().reload(); + AOEngine::instance().reload(false); updateList(); } diff --git a/indra/newview/aoengine.cpp b/indra/newview/aoengine.cpp index a6358ba65f..6ad5860a50 100644 --- a/indra/newview/aoengine.cpp +++ b/indra/newview/aoengine.cpp @@ -66,7 +66,7 @@ AOEngine::AOEngine() : AOEngine::~AOEngine() { - clear(); + clear(false); } void AOEngine::init() @@ -80,10 +80,23 @@ void AOEngine::onLoginComplete() AOEngine::instance().init(); } -void AOEngine::clear() +void AOEngine::clear( bool aFromTimer ) { + mOldSets.insert( mOldSets.end(), mSets.begin(), mSets.end() ); mSets.clear(); + mCurrentSet=0; + + // FIRE-3801; We cannot delete any AOSet object if we're called from a timer tick. AOSet is derived from LLEventTimer and destruction will + // fail in ~LLInstanceTracker when a destructor runs during iteration. + if( !aFromTimer ) + { + std::for_each( mOldSets.begin(), mOldSets.end(), DeletePointer( ) ); + mOldSets.clear(); + + std::for_each( mOldImportSets.begin(), mOldImportSets.end(), DeletePointer() ); + mOldImportSets.clear(); + } } void AOEngine::stopAllStandVariants() @@ -986,7 +999,7 @@ void AOEngine::update() } } -void AOEngine::reload() +void AOEngine::reload( bool aFromTimer ) { BOOL wasEnabled=mEnabled; @@ -998,7 +1011,7 @@ void AOEngine::reload() gAgent.stopCurrentAnimations(); mLastOverriddenMotion=ANIM_AGENT_STAND; - clear(); + clear( aFromTimer ); mAOFolder.setNull(); mTimerCollection.enableInventoryTimer(TRUE); tick(); @@ -1531,10 +1544,10 @@ void AOEngine::parseNotecard(const char* buffer) mTimerCollection.enableImportTimer(TRUE); mImportRetryCount=0; - processImport(); + processImport(false); } -void AOEngine::processImport() +void AOEngine::processImport( bool aFromTimer ) { if(mImportCategory.isNull()) { @@ -1597,10 +1610,10 @@ void AOEngine::processImport() if(allComplete) { mTimerCollection.enableImportTimer(FALSE); - delete mImportSet; + mOldImportSets.push_back( mImportSet ); // FIRE-3801; Cannot delete here, or LLInstanceTracker gets upset. Just remember and delete mOldImportSets once we can. mImportSet=0; mImportCategory.setNull(); - reload(); + reload( aFromTimer ); } } @@ -1673,12 +1686,12 @@ BOOL AOTimerCollection::tick() if(mReloadTimer) { lldebugs << "Reload timer tick()" << llendl; - AOEngine::instance().reload(); + AOEngine::instance().reload(true); } if(mImportTimer) { lldebugs << "Import timer tick()" << llendl; - AOEngine::instance().processImport(); + AOEngine::instance().processImport(true); } // always return FALSE or the LLEventTimer will be deleted -> crash diff --git a/indra/newview/aoengine.h b/indra/newview/aoengine.h index 9d5d9fb6a3..4535f58866 100644 --- a/indra/newview/aoengine.h +++ b/indra/newview/aoengine.h @@ -101,9 +101,9 @@ class AOEngine const LLUUID override(const LLUUID motion,BOOL start); void tick(); void update(); - void reload(); + void reload(bool); void reloadStateAnimations(AOSet::AOState* state); - void clear(); + void clear( bool ); const LLUUID getAOFolder(); @@ -116,7 +116,7 @@ class AOEngine void checkBelowWater(BOOL yes); BOOL importNotecard(const LLInventoryItem* item); - void processImport(); + void processImport( bool ); BOOL swapWithPrevious(AOSet::AOState* state,S32 index); BOOL swapWithNext(AOSet::AOState* state,S32 index); @@ -188,10 +188,12 @@ class AOEngine LLUUID mLastOverriddenMotion; std::vector mSets; + std::vector mOldSets; AOSet* mCurrentSet; AOSet* mDefaultSet; AOSet* mImportSet; + std::vector mOldImportSets; LLUUID mImportCategory; S32 mImportRetryCount; };