From 6ecae04d358cc27bc4890778a1493b3818236fb9 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Fri, 17 Feb 2012 15:33:09 -0600
Subject: [PATCH] SH-2941 Fix for crash on shutdown due to race condition
 between LLCurl and LLMeshRepository

---
 indra/newview/llmeshrepository.cpp | 288 ++++++++++++-----------------
 1 file changed, 118 insertions(+), 170 deletions(-)

diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index bd202101909..f461c7e46fb 100755
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -508,6 +508,7 @@ void LLMeshRepoThread::run()
 			
 			while (!mLODReqQ.empty() && count < MAX_MESH_REQUESTS_PER_SECOND && sActiveLODRequests < sMaxConcurrentRequests)
 			{
+				if (mMutex)
 				{
 					mMutex->lock();
 					LODRequest req = mLODReqQ.front();
@@ -525,6 +526,7 @@ void LLMeshRepoThread::run()
 
 			while (!mHeaderReqQ.empty() && count < MAX_MESH_REQUESTS_PER_SECOND && sActiveHeaderRequests < sMaxConcurrentRequests)
 			{
+				if (mMutex)
 				{
 					mMutex->lock();
 					HeaderRequest req = mHeaderReqQ.front();
@@ -671,6 +673,12 @@ std::string LLMeshRepoThread::constructUrl(LLUUID mesh_id)
 
 bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
 { //protected by mMutex
+	
+	if (!mHeaderMutex)
+	{
+		return false;
+	}
+
 	mHeaderMutex->lock();
 
 	if (mMeshHeader.find(mesh_id) == mMeshHeader.end())
@@ -747,6 +755,11 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
 
 bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
 { //protected by mMutex
+	if (!mHeaderMutex)
+	{
+		return false;
+	}
+
 	mHeaderMutex->lock();
 
 	if (mMeshHeader.find(mesh_id) == mMeshHeader.end())
@@ -824,6 +837,11 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
 
 bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
 { //protected by mMutex
+	if (!mHeaderMutex)
+	{
+		return false;
+	}
+
 	mHeaderMutex->lock();
 
 	if (mMeshHeader.find(mesh_id) == mMeshHeader.end())
@@ -950,6 +968,11 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, U32& c
 //return false if failed to get mesh lod.
 bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, U32& count)
 { //protected by mMutex
+	if (!mHeaderMutex)
+	{
+		return false;
+	}
+
 	mHeaderMutex->lock();
 
 	bool retval = true;
@@ -1068,10 +1091,11 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat
 	{
 		LLUUID mesh_id = mesh_params.getSculptID();
 		
-		mHeaderMutex->lock();
-		mMeshHeaderSize[mesh_id] = header_size;
-		mMeshHeader[mesh_id] = header;
-		mHeaderMutex->unlock();
+		{
+			LLMutexLock lock(mHeaderMutex);
+			mMeshHeaderSize[mesh_id] = header_size;
+			mMeshHeader[mesh_id] = header;
+			}
 
 		//check for pending requests
 		pending_lod_map::iterator iter = mPendingLOD.find(mesh_params);
@@ -1646,6 +1670,11 @@ void LLMeshUploadThread::requestWholeModelFee()
 
 void LLMeshRepoThread::notifyLoadedMeshes()
 {
+	if (!mMutex)
+	{
+		return;
+	}
+
 	while (!mLoadedQ.empty())
 	{
 		mMutex->lock();
@@ -2357,93 +2386,92 @@ void LLMeshRepository::notifyLoadedMeshes()
 		}
 	}
 
-	mMeshMutex->lock();	
-	mThread->mMutex->lock();
-		
-	//popup queued error messages from background threads
-	while (!mUploadErrorQ.empty())
 	{
-		LLNotificationsUtil::add("MeshUploadError", mUploadErrorQ.front());
-		mUploadErrorQ.pop();
-	}
+		LLMutexLock lock1(mMeshMutex);
+		LLMutexLock lock2(mThread->mMutex);
+		
+		//popup queued error messages from background threads
+		while (!mUploadErrorQ.empty())
+		{
+			LLNotificationsUtil::add("MeshUploadError", mUploadErrorQ.front());
+			mUploadErrorQ.pop();
+		}
 
-	S32 push_count = LLMeshRepoThread::sMaxConcurrentRequests-(LLMeshRepoThread::sActiveHeaderRequests+LLMeshRepoThread::sActiveLODRequests);
+		S32 push_count = LLMeshRepoThread::sMaxConcurrentRequests-(LLMeshRepoThread::sActiveHeaderRequests+LLMeshRepoThread::sActiveLODRequests);
 
-	if (push_count > 0)
-	{
-		//calculate "score" for pending requests
+		if (push_count > 0)
+		{
+			//calculate "score" for pending requests
 
-		//create score map
-		std::map<LLUUID, F32> score_map;
+			//create score map
+			std::map<LLUUID, F32> score_map;
 
-		for (U32 i = 0; i < 4; ++i)
-		{
-			for (mesh_load_map::iterator iter = mLoadingMeshes[i].begin();  iter != mLoadingMeshes[i].end(); ++iter)
+			for (U32 i = 0; i < 4; ++i)
 			{
-				F32 max_score = 0.f;
-				for (std::set<LLUUID>::iterator obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter)
+				for (mesh_load_map::iterator iter = mLoadingMeshes[i].begin();  iter != mLoadingMeshes[i].end(); ++iter)
 				{
-					LLViewerObject* object = gObjectList.findObject(*obj_iter);
-
-					if (object)
+					F32 max_score = 0.f;
+					for (std::set<LLUUID>::iterator obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter)
 					{
-						LLDrawable* drawable = object->mDrawable;
-						if (drawable)
+						LLViewerObject* object = gObjectList.findObject(*obj_iter);
+
+						if (object)
 						{
-							F32 cur_score = drawable->getRadius()/llmax(drawable->mDistanceWRTCamera, 1.f);
-							max_score = llmax(max_score, cur_score);
+							LLDrawable* drawable = object->mDrawable;
+							if (drawable)
+							{
+								F32 cur_score = drawable->getRadius()/llmax(drawable->mDistanceWRTCamera, 1.f);
+								max_score = llmax(max_score, cur_score);
+							}
 						}
 					}
-				}
 				
-				score_map[iter->first.getSculptID()] = max_score;
+					score_map[iter->first.getSculptID()] = max_score;
+				}
+			}
+
+			//set "score" for pending requests
+			for (std::vector<LLMeshRepoThread::LODRequest>::iterator iter = mPendingRequests.begin(); iter != mPendingRequests.end(); ++iter)
+			{
+				iter->mScore = score_map[iter->mMeshParams.getSculptID()];
+			}
+
+			//sort by "score"
+			std::sort(mPendingRequests.begin(), mPendingRequests.end(), LLMeshRepoThread::CompareScoreGreater());
+
+			while (!mPendingRequests.empty() && push_count > 0)
+			{
+				LLMeshRepoThread::LODRequest& request = mPendingRequests.front();
+				mThread->loadMeshLOD(request.mMeshParams, request.mLOD);
+				mPendingRequests.erase(mPendingRequests.begin());
+				LLMeshRepository::sLODPending--;
+				push_count--;
 			}
 		}
 
-		//set "score" for pending requests
-		for (std::vector<LLMeshRepoThread::LODRequest>::iterator iter = mPendingRequests.begin(); iter != mPendingRequests.end(); ++iter)
+		//send skin info requests
+		while (!mPendingSkinRequests.empty())
 		{
-			iter->mScore = score_map[iter->mMeshParams.getSculptID()];
+			mThread->loadMeshSkinInfo(mPendingSkinRequests.front());
+			mPendingSkinRequests.pop();
 		}
-
-		//sort by "score"
-		std::sort(mPendingRequests.begin(), mPendingRequests.end(), LLMeshRepoThread::CompareScoreGreater());
-
-		while (!mPendingRequests.empty() && push_count > 0)
+	
+		//send decomposition requests
+		while (!mPendingDecompositionRequests.empty())
 		{
-			LLMeshRepoThread::LODRequest& request = mPendingRequests.front();
-			mThread->loadMeshLOD(request.mMeshParams, request.mLOD);
-			mPendingRequests.erase(mPendingRequests.begin());
-			LLMeshRepository::sLODPending--;
-			push_count--;
+			mThread->loadMeshDecomposition(mPendingDecompositionRequests.front());
+			mPendingDecompositionRequests.pop();
 		}
-	}
-
-	//send skin info requests
-	while (!mPendingSkinRequests.empty())
-	{
-		mThread->loadMeshSkinInfo(mPendingSkinRequests.front());
-		mPendingSkinRequests.pop();
-	}
 	
-	//send decomposition requests
-	while (!mPendingDecompositionRequests.empty())
-	{
-		mThread->loadMeshDecomposition(mPendingDecompositionRequests.front());
-		mPendingDecompositionRequests.pop();
-	}
+		//send physics shapes decomposition requests
+		while (!mPendingPhysicsShapeRequests.empty())
+		{
+			mThread->loadMeshPhysicsShape(mPendingPhysicsShapeRequests.front());
+			mPendingPhysicsShapeRequests.pop();
+		}
 	
-	//send physics shapes decomposition requests
-	while (!mPendingPhysicsShapeRequests.empty())
-	{
-		mThread->loadMeshPhysicsShape(mPendingPhysicsShapeRequests.front());
-		mPendingPhysicsShapeRequests.pop();
+		mThread->notifyLoadedMeshes();
 	}
-	
-	mThread->notifyLoadedMeshes();
-
-	mThread->mMutex->unlock();
-	mMeshMutex->unlock();
 
 	mThread->mSignal->signal();
 }
@@ -3091,13 +3119,14 @@ void LLPhysicsDecomp::doDecomposition()
 			num_hulls = LLConvexDecomposition::getInstance()->getNumHullsFromStage(stage);
 		}
 		
-		mMutex->lock();
-		mCurRequest->mHull.clear();
-		mCurRequest->mHull.resize(num_hulls);
+		{
+			LLMutexLock lock(mMutex);
+			mCurRequest->mHull.clear();
+			mCurRequest->mHull.resize(num_hulls);
 
-		mCurRequest->mHullMesh.clear();
-		mCurRequest->mHullMesh.resize(num_hulls);
-		mMutex->unlock();
+			mCurRequest->mHullMesh.clear();
+			mCurRequest->mHullMesh.resize(num_hulls);
+		}
 
 		for (S32 i = 0; i < num_hulls; ++i)
 		{
@@ -3121,14 +3150,14 @@ void LLPhysicsDecomp::doDecomposition()
 
 			get_vertex_buffer_from_mesh(mesh, mCurRequest->mHullMesh[i]);
 			
-			mMutex->lock();
-			mCurRequest->mHull[i] = p;
-			mMutex->unlock();
+			{
+				LLMutexLock lock(mMutex);
+				mCurRequest->mHull[i] = p;
+			}
 		}
 	
 		{
 			LLMutexLock lock(mMutex);
-
 			mCurRequest->setStatusMessage("FAIL");
 			completeCurrent();						
 		}
@@ -3196,7 +3225,6 @@ void LLPhysicsDecomp::doDecompositionSingleHull()
 	
 	LLCDMeshData mesh;	
 
-#if 1
 	setMeshData(mesh, true);
 
 	LLCDResult ret = decomp->buildSingleHull() ;
@@ -3207,11 +3235,12 @@ void LLPhysicsDecomp::doDecompositionSingleHull()
 	}
 	else
 	{
-		mMutex->lock();
-		mCurRequest->mHull.clear();
-		mCurRequest->mHull.resize(1);
-		mCurRequest->mHullMesh.clear();
-		mMutex->unlock();
+		{
+			LLMutexLock lock(mMutex);
+			mCurRequest->mHull.clear();
+			mCurRequest->mHull.resize(1);
+			mCurRequest->mHullMesh.clear();
+		}
 
 		std::vector<LLVector3> p;
 		LLCDHull hull;
@@ -3227,93 +3256,12 @@ void LLPhysicsDecomp::doDecompositionSingleHull()
 			p.push_back(vert);
 			v = (F32*) (((U8*) v) + hull.mVertexStrideBytes);
 		}
-						
-		mMutex->lock();
-		mCurRequest->mHull[0] = p;
-		mMutex->unlock();	
-	}		
-#else
-	setMeshData(mesh, false);
-
-	//set all parameters to default
-	std::map<std::string, const LLCDParam*> param_map;
-
-	static const LLCDParam* params = NULL;
-	static S32 param_count = 0;
-
-	if (!params)
-	{
-		param_count = decomp->getParameters(&params);
-	}
-	
-	for (S32 i = 0; i < param_count; ++i)
-	{
-		decomp->setParam(params[i].mName, params[i].mDefault.mIntOrEnumValue);
-	}
-
-	const S32 STAGE_DECOMPOSE = mStageID["Decompose"];	
-	const S32 STAGE_SIMPLIFY = mStageID["Simplify"];
-	const S32 DECOMP_PREVIEW = 0;
-	const S32 SIMPLIFY_RETAIN = 0;
-	
-	decomp->setParam("Decompose Quality", DECOMP_PREVIEW);
-	decomp->setParam("Simplify Method", SIMPLIFY_RETAIN);
-	decomp->setParam("Retain%", 0.f);
-
-	LLCDResult ret = LLCD_OK;
-	ret = decomp->executeStage(STAGE_DECOMPOSE);
-	
-	if (ret)
-	{
-		llwarns << "Could not execute decomposition stage when attempting to create single hull." << llendl;
-		make_box(mCurRequest);
-	}
-	else
-	{
-		ret = decomp->executeStage(STAGE_SIMPLIFY);
-
-		if (ret)
-		{
-			llwarns << "Could not execute simiplification stage when attempting to create single hull." << llendl;
-			make_box(mCurRequest);
-		}
-		else
+					
 		{
-			S32 num_hulls =0;
-			if (LLConvexDecomposition::getInstance() != NULL)
-			{
-				num_hulls = LLConvexDecomposition::getInstance()->getNumHullsFromStage(STAGE_SIMPLIFY);
-			}
-			
-			mMutex->lock();
-			mCurRequest->mHull.clear();
-			mCurRequest->mHull.resize(num_hulls);
-			mCurRequest->mHullMesh.clear();
-			mMutex->unlock();
-
-			for (S32 i = 0; i < num_hulls; ++i)
-			{
-				std::vector<LLVector3> p;
-				LLCDHull hull;
-				// if LLConvexDecomposition is a stub, num_hulls should have been set to 0 above, and we should not reach this code
-				LLConvexDecomposition::getInstance()->getHullFromStage(STAGE_SIMPLIFY, i, &hull);
-
-				const F32* v = hull.mVertexBase;
-
-				for (S32 j = 0; j < hull.mNumVertices; ++j)
-				{
-					LLVector3 vert(v[0], v[1], v[2]); 
-					p.push_back(vert);
-					v = (F32*) (((U8*) v) + hull.mVertexStrideBytes);
-				}
-						
-				mMutex->lock();
-				mCurRequest->mHull[i] = p;
-				mMutex->unlock();
-			}
+			LLMutexLock lock(mMutex);
+			mCurRequest->mHull[0] = p;
 		}
-	}
-#endif
+	}		
 
 	{
 		completeCurrent();
-- 
GitLab