From 7af46e7fe37552175c46a9366e9574bb9c716a68 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 27 Jun 2017 20:24:15 +0100
Subject: [PATCH] SL-722 - defer markDead() for LLControlAvatar when unlinking.
 Fixes asset crash in pipeline. Also added various checks for mDrawable null
 in llvoavatar.cpp.

---
 indra/newview/llcontrolavatar.cpp | 24 ++++++++++++--
 indra/newview/llcontrolavatar.h   |  9 +++++
 indra/newview/llviewerobject.cpp  |  2 +-
 indra/newview/llvoavatar.cpp      | 55 +++++++++++++++++++++----------
 4 files changed, 70 insertions(+), 20 deletions(-)

diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp
index 26c4865e4c7..6fc3d52fe7a 100644
--- a/indra/newview/llcontrolavatar.cpp
+++ b/indra/newview/llcontrolavatar.cpp
@@ -35,7 +35,8 @@
 LLControlAvatar::LLControlAvatar(const LLUUID& id, const LLPCode pcode, LLViewerRegion* regionp) :
     LLVOAvatar(id, pcode, regionp),
     mPlaying(false),
-    mGlobalScale(1.0f)
+    mGlobalScale(1.0f),
+    mMarkedForDeath(false)
 {
     mIsControlAvatar = true;
     mEnableDefaultMotions = false;
@@ -155,7 +156,6 @@ LLControlAvatar *LLControlAvatar::createControlAvatar(LLVOVolume *obj)
 	cav->mSpecialRenderMode = 1;
 	cav->updateJointLODs();
 	cav->updateGeometry(cav->mDrawable);
-	//cav->startMotion(ANIM_AGENT_STAND, 5.0f);
 	cav->hideSkirt();
 
     // Sync up position/rotation with object
@@ -164,3 +164,23 @@ LLControlAvatar *LLControlAvatar::createControlAvatar(LLVOVolume *obj)
     return cav;
 }
 
+void LLControlAvatar::markForDeath()
+{
+    mMarkedForDeath = true;
+}
+
+// static
+void LLControlAvatar::idleUpdate(LLAgent &agent, const F64 &time)
+{
+    if (mMarkedForDeath)
+    {
+        markDead();
+        mMarkedForDeath = false;
+    }
+    else
+    {
+        LLVOAvatar::idleUpdate(agent,time);
+    }
+}
+
+
diff --git a/indra/newview/llcontrolavatar.h b/indra/newview/llcontrolavatar.h
index bb54cc5b2d5..5cca0ab9dd7 100644
--- a/indra/newview/llcontrolavatar.h
+++ b/indra/newview/llcontrolavatar.h
@@ -46,11 +46,20 @@ class LLControlAvatar:
     void recursiveScaleJoint(LLJoint *joint, F32 factor);
     static LLControlAvatar *createControlAvatar(LLVOVolume *obj);
 
+    // Delayed kill so we don't make graphics pipeline unhappy calling
+    // markDead() inside other graphics pipeline operations.
+    void markForDeath();
+
+    virtual void idleUpdate(LLAgent &agent, const F64 &time);
+    
     bool mPlaying;
 
     F32 mGlobalScale;
 
     LLVOVolume *mRootVolp;
+
+    bool mMarkedForDeath;
+
 };
 
 #endif //LL_CONTROLAVATAR_H
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index bd0e864f80c..06efb1bc3aa 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -2958,7 +2958,7 @@ void LLViewerObject::unlinkControlAvatar()
         // This will remove the entire linkset from the control avatar
         LLControlAvatar *av = mControlAvatar;
         mControlAvatar = NULL;
-        av->markDead();
+        av->markForDeath();
     }
     // For non-root prims, removing from the linkset will
     // automatically remove the control avatar connection.
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index c268ab5f3c6..4ed924f828d 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1225,8 +1225,6 @@ const LLVector3 LLVOAvatar::getRenderPosition() const
 	{
 		return getPosition() * mDrawable->getParent()->getRenderMatrix();
 	}
-	
-	
 }
 
 void LLVOAvatar::updateDrawable(BOOL force_damped)
@@ -1243,6 +1241,10 @@ void LLVOAvatar::onShift(const LLVector4a& shift_vector)
 
 void LLVOAvatar::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax)
 {
+    if (mDrawable.isNull())
+    {
+        return;
+    }
 	if (isImpostor() && !needsImpostorUpdate())
 	{
 		LLVector3 delta = getRenderPosition() -
@@ -1971,15 +1973,15 @@ void LLVOAvatar::releaseMeshData()
 		LLFace* facep = mDrawable->getFace(0);
 		if (facep)
 		{
-		facep->setSize(0, 0);
-		for(S32 i = mNumInitFaces ; i < mDrawable->getNumFaces(); i++)
-		{
-			facep = mDrawable->getFace(i);
+            facep->setSize(0, 0);
+            for(S32 i = mNumInitFaces ; i < mDrawable->getNumFaces(); i++)
+            {
+                facep = mDrawable->getFace(i);
 				if (facep)
 				{
-			facep->setSize(0, 0);
-		}
-	}
+                    facep->setSize(0, 0);
+                }
+            }
 		}
 	}
 	
@@ -2003,6 +2005,10 @@ void LLVOAvatar::releaseMeshData()
 void LLVOAvatar::restoreMeshData()
 {
 	llassert(!isSelf());
+    if (mDrawable.isNull())
+    {
+        return;
+    }
 	
 	//LL_INFOS() << "Restoring" << LL_ENDL;
 	mMeshValid = TRUE;
@@ -2580,13 +2586,16 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update)
 		}
 	}
 
-	mDrawable->movePartition();
-	
-	//force a move if sitting on an active object
-	if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive())
-	{
-		gPipeline.markMoved(mDrawable, TRUE);
-	}
+    if (mDrawable.notNull())
+    {
+        mDrawable->movePartition();
+        
+        //force a move if sitting on an active object
+        if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive())
+        {
+            gPipeline.markMoved(mDrawable, TRUE);
+        }
+    }
 }
 
 void LLVOAvatar::idleUpdateAppearanceAnimation()
@@ -3504,7 +3513,9 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 	//--------------------------------------------------------------------
 
 	bool visually_muted = isVisuallyMuted();
-	if (visible && (!isSelf() || visually_muted) && !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter)
+    // AXON FIXME this expression is a crawling horror
+	if (mDrawable.notNull() && visible && (!isSelf() || visually_muted) && 
+        !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter)
 	{
 		const LLVector4a* ext = mDrawable->getSpatialExtents();
 		LLVector4a size;
@@ -4223,6 +4234,11 @@ U32 LLVOAvatar::renderSkinned()
 		return num_indices;
 	}
 
+    if (mDrawable.isNull())
+    {
+		return num_indices;
+    }
+
 	LLFace* face = mDrawable->getFace(0);
 
 	bool needs_rebuild = !face || !face->getVertexBuffer() || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY);
@@ -8845,6 +8861,11 @@ void LLVOAvatar::updateFreezeCounter(S32 counter)
 
 BOOL LLVOAvatar::updateLOD()
 {
+    if (mDrawable.isNull())
+    {
+        return FALSE;
+    }
+    
 	if (isImpostor() && 0 != mDrawable->getNumFaces() && mDrawable->getFace(0)->hasGeometry())
 	{
 		return TRUE;
-- 
GitLab