summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXiaohong Bao <bao@lindenlab.com>2013-11-19 19:33:28 -0700
committerXiaohong Bao <bao@lindenlab.com>2013-11-19 19:33:28 -0700
commit4d70e20ede4ad404bf8ddeca2effb1171b471bcc (patch)
treea1a26ecabaaf6b8ea01e124cf2e16c16b63a913d
parenta868b7ed41d8b7d04ae47490564cdc35bcfbac1a (diff)
fix for SH-4629: Interesting: crash at LLViewerRegion::killObject
-rwxr-xr-xindra/newview/llviewerregion.cpp42
-rwxr-xr-xindra/newview/llviewerregion.h2
2 files changed, 39 insertions, 5 deletions
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index e3ebd2fc2a..f71d0a7a64 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -923,6 +923,21 @@ void LLViewerRegion::addActiveCacheEntry(LLVOCacheEntry* entry)
mImpl->mActiveSet.insert(entry);
}
+//remove vo entry which is in mImpl->mActiveSet but not in rendering pipeline.
+//this is caused by mImpl->mActiveSet failing to remove this entry somehow.
+void LLViewerRegion::removeDanglingEntry(LLVOCacheEntry* entry)
+{
+ if(mDead || !entry)
+ {
+ return;
+ }
+
+ mImpl->mVisibleEntries.erase(entry);
+ mImpl->mActiveSet.erase(entry);
+ mImpl->mWaitingSet.erase(entry);
+ entry->setState(LLVOCacheEntry::INACTIVE);
+}
+
void LLViewerRegion::removeActiveCacheEntry(LLVOCacheEntry* entry, LLDrawable* drawablep)
{
if(mDead || !entry)
@@ -1403,6 +1418,8 @@ void LLViewerRegion::killInvisibleObjects(F32 max_time)
}
std::vector<LLDrawable*> delete_list;
+ std::vector<LLVOCacheEntry*> dangling_list;
+
S32 update_counter = llmin(max_update, mImpl->mActiveSet.size());
LLVOCacheEntry::vocache_entry_set_t::iterator iter = mImpl->mActiveSet.upper_bound(mLastVisitedEntry);
@@ -1417,9 +1434,17 @@ void LLViewerRegion::killInvisibleObjects(F32 max_time)
continue; //skip child objects, they are removed with their parent.
}
- if(!(*iter)->isAnyVisible(camera_origin, local_origin, back_threshold) && (*iter)->mLastCameraUpdated < sLastCameraUpdated)
+ LLVOCacheEntry* vo_entry = *iter;
+ if(!vo_entry->getEntry() || !vo_entry->getEntry()->getDrawable())
+ {
+ //sometimes mImpl->mActiveSet fails to erase some entry, causing this dangling case.
+ dangling_list.push_back(vo_entry);
+ continue;
+ }
+
+ if(!vo_entry->isAnyVisible(camera_origin, local_origin, back_threshold) && vo_entry->mLastCameraUpdated < sLastCameraUpdated)
{
- killObject((*iter), delete_list);
+ killObject(vo_entry, delete_list);
}
if(max_time < update_timer.getElapsedTimeF32()) //time out
@@ -1441,13 +1466,22 @@ void LLViewerRegion::killInvisibleObjects(F32 max_time)
if(!delete_list.empty())
{
mInvisibilityCheckHistory |= 1;
- for(S32 i = 0; i < delete_list.size(); i++)
+ S32 count = delete_list.size();
+ for(S32 i = 0; i < count; i++)
{
gObjectList.killObject(delete_list[i]->getVObj());
}
delete_list.clear();
}
+ if(!dangling_list.empty())
+ {
+ for(S32 i = 0; i < dangling_list.size(); i++)
+ {
+ removeDanglingEntry(dangling_list[i]);
+ }
+ }
+
return;
}
@@ -1457,7 +1491,7 @@ void LLViewerRegion::killObject(LLVOCacheEntry* entry, std::vector<LLDrawable*>&
LLDrawable* drawablep = (LLDrawable*)entry->getEntry()->getDrawable();
llassert(drawablep);
- if(!drawablep->getParent())
+ if(drawablep && !drawablep->getParent())
{
LLViewerObject::const_child_list_t& child_list = drawablep->getVObj()->getChildren();
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index a6c1eb65d4..6889db7880 100755
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -386,7 +386,7 @@ private:
void removeFromVOCacheTree(LLVOCacheEntry* entry);
void replaceVisibleCacheEntry(LLVOCacheEntry* old_entry, LLVOCacheEntry* new_entry);
void killCacheEntry(LLVOCacheEntry* entry); //physically delete the cache entry
-
+ void removeDanglingEntry(LLVOCacheEntry* entry);
void killInvisibleObjects(F32 max_time);
void createVisibleObjects(F32 max_time);
void updateVisibleEntries(F32 max_time); //update visible entries