From b49170b732e6e4b2cf11b40c12b3d75a8709cf5c Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Fri, 31 Jan 2014 18:24:55 -0700
Subject: [PATCH] fix some flaws for memory corruption

---
 indra/newview/lldrawable.cpp     | 11 +++++----
 indra/newview/llviewerregion.cpp | 39 ++++++++++++++++----------------
 indra/newview/llviewerregion.h   |  2 +-
 indra/newview/llvocache.cpp      | 25 ++++++++++++++++++++
 indra/newview/llvocache.h        |  4 +++-
 5 files changed, 54 insertions(+), 27 deletions(-)

diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 7414b24811f..c56006d9a36 100755
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -128,13 +128,14 @@ void LLDrawable::init(bool new_entry)
 		{
 			vo_entry->setOctreeEntry(mEntry);
 		}
-		else if(vo_entry->getNumOfChildren() > 0)
-		{
-			getRegion()->addVisibleCacheEntry(vo_entry); //to load all children.
-		}
-	
+		
 		getRegion()->addActiveCacheEntry(vo_entry);
 
+		if(vo_entry->getNumOfChildren() > 0)
+		{
+			getRegion()->addVisibleChildCacheEntry(vo_entry, NULL); //to load all children.
+		}		
+
 		llassert(!vo_entry->getGroup()); //not in the object cache octree.
 	}
 	
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 3d8afcceb05..e2143babcf1 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1007,37 +1007,36 @@ void LLViewerRegion::removeFromVOCacheTree(LLVOCacheEntry* entry)
 	mImpl->mVOCachePartition->removeEntry(entry->getEntry());	
 }
 
-//add the visible entries
-void LLViewerRegion::addVisibleCacheEntry(LLVOCacheEntry* entry)
+//add child objects as visible entries
+void LLViewerRegion::addVisibleChildCacheEntry(LLVOCacheEntry* parent, LLVOCacheEntry* child)
 {
-	if(mDead || !entry || !entry->getEntry() || !entry->isValid())
-	{
-		return; 
-	}
-
-	if(entry->isState(LLVOCacheEntry::IN_QUEUE))
+	if(mDead)
 	{
 		return;
 	}
 
-	if(entry->isState(LLVOCacheEntry::INACTIVE))
+	if(parent && (!parent->isValid() || !parent->isState(LLVOCacheEntry::ACTIVE)))
 	{
-		entry->setState(LLVOCacheEntry::IN_QUEUE);
+		return; //parent must be valid and in rendering pipeline
 	}
 
-	if(!entry->isState(LLVOCacheEntry::ACTIVE))
+	if(child && (!child->getEntry() || !child->isValid() || !child->isState(LLVOCacheEntry::INACTIVE)))
 	{
-		mImpl->mVisibleEntries.insert(entry);
+		return; //child must be valid and not in the rendering pipeline
 	}
 
-	//add all children
-	if(entry->getNumOfChildren() > 0)
+	if(child)
 	{
-		LLVOCacheEntry* child = entry->getChild();
+		child->setState(LLVOCacheEntry::IN_QUEUE);
+		mImpl->mVisibleEntries.insert(child);
+	}	
+	else if(parent && parent->getNumOfChildren() > 0) //add all children
+	{
+		child = parent->getChild();
 		while(child != NULL)
 		{
-			addVisibleCacheEntry(child);
-			child = entry->getChild();
+			addVisibleCacheEntry(NULL, child);
+			child = parent->getChild();
 		}
 	}
 }
@@ -2002,7 +2001,7 @@ void LLViewerRegion::findOrphans(U32 parent_id)
 		for(S32 i = 0; i < children->size(); i++)
 		{
 			//parent is visible, so is the child.
-			addVisibleCacheEntry(getCacheEntry((*children)[i]));
+			addVisibleChildCacheEntry(NULL, getCacheEntry((*children)[i]));
 		}
 		children->clear();
 		mOrphanMap.erase(parent_id);
@@ -2106,7 +2105,7 @@ void LLViewerRegion::decodeBoundingInfo(LLVOCacheEntry* entry)
 				if(isNonCacheableObjectCreated(parent_id))
 				{
 					//parent is visible, so is the child.
-					addVisibleCacheEntry(entry);
+					addVisibleChildCacheEntry(NULL, entry);
 				}
 				else
 				{
@@ -2124,7 +2123,7 @@ void LLViewerRegion::decodeBoundingInfo(LLVOCacheEntry* entry)
 			if(!parent->isState(LLVOCacheEntry::INACTIVE)) 
 			{
 				//parent is visible, so is the child.
-				addVisibleCacheEntry(entry);
+				addVisibleCacheEntry(parent, entry);
 			}
 			else
 			{
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 7ce191fe8fb..7f6a8186a52 100755
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -232,7 +232,7 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	void idleUpdate(F32 max_update_time);
 	void lightIdleUpdate();
 	bool addVisibleGroup(LLViewerOctreeGroup* group);
-	void addVisibleCacheEntry(LLVOCacheEntry* entry);
+	void addVisibleChildCacheEntry(LLVOCacheEntry* parent, LLVOCacheEntry* child);
 	void addActiveCacheEntry(LLVOCacheEntry* entry);
 	void removeActiveCacheEntry(LLVOCacheEntry* entry, LLDrawable* drawablep);	
 	void killCacheEntry(U32 local_id); //physically delete the cache entry	
diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp
index 8af6d74ad72..0ff38ebdc87 100755
--- a/indra/newview/llvocache.cpp
+++ b/indra/newview/llvocache.cpp
@@ -194,6 +194,31 @@ void LLVOCacheEntry::updateEntry(U32 crc, LLDataPackerBinaryBuffer &dp)
 	mDP = dp;
 }
 
+void LLVOCacheEntry::setParentID(U32 id) 
+{
+	if(mParentID != id)
+	{
+		removeAllChildren();
+		mParentID = id;
+	}
+}
+
+void LLVOCacheEntry::removeAllChildren()
+{
+	if(mChildrenList.empty())
+	{
+		return;
+	}
+
+	for(vocache_entry_set_t::iterator iter = mChildrenList.begin(); iter != mChildrenList.end(); ++iter)
+ 	{
+		*iter->setParentID(0);
+ 	}
+	mChildrenList.clear();
+
+	return;
+}
+
 //virtual 
 void LLVOCacheEntry::setOctreeEntry(LLViewerOctreeEntry* entry)
 {
diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h
index 7396de47099..082f5f0b1d6 100755
--- a/indra/newview/llvocache.h
+++ b/indra/newview/llvocache.h
@@ -113,11 +113,13 @@ class LLVOCacheEntry
 	
 	/*virtual*/ void setOctreeEntry(LLViewerOctreeEntry* entry);
 
-	void setParentID(U32 id) {mParentID = id;}
+	void setParentID(U32 id);
 	U32  getParentID() const {return mParentID;}
+	bool isChild() const {return mParentID > 0;}
 
 	void addChild(LLVOCacheEntry* entry);
 	void removeChild(LLVOCacheEntry* entry);
+	void removeAllChildren();
 	LLVOCacheEntry* getChild(); //remove the first child, and return it.
 	S32  getNumOfChildren() const  {return mChildrenList.size();}
 	
-- 
GitLab