From 961e50aab40fe09632e4f3f9aa385abd0fb42735 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Tue, 4 Jan 2011 16:22:38 -0700
Subject: clear some LLPointer issues for SH-694: check if there are any other
 LLPointer issues in the mesh model uploading flow and fix them if exist.

---
 indra/newview/llfloatermodelpreview.cpp | 42 ++++++++++++++++++++++++++-------
 indra/newview/llfloatermodelpreview.h   |  3 ++-
 indra/newview/llmeshrepository.cpp      | 17 ++++++++-----
 indra/newview/llmeshrepository.h        |  1 +
 indra/newview/llviewertexturelist.cpp   |  2 +-
 5 files changed, 48 insertions(+), 17 deletions(-)

diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 68b9e5d23d..d63c8244df 100755
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -1590,6 +1590,35 @@ void LLModelLoader::run()
 	}
 }
 
+//called in the main thread
+void LLModelLoader::loadTextures()
+{
+	BOOL is_paused = isPaused() ;
+	pause() ; //pause the loader 
+
+	for(scene::iterator iter = mScene.begin(); iter != mScene.end(); ++iter)
+	{
+		for(U32 i = 0 ; i < iter->second.size(); i++)
+		{
+			for(U32 j = 0 ; j < iter->second[i].mMaterial.size() ; j++)
+			{
+				if(!iter->second[i].mMaterial[j].mDiffuseMapFilename.empty())
+				{
+					iter->second[i].mMaterial[j].mDiffuseMap = 
+						LLViewerTextureManager::getFetchedTextureFromUrl("file://" + iter->second[i].mMaterial[j].mDiffuseMapFilename, TRUE, LLViewerTexture::BOOST_PREVIEW);
+					iter->second[i].mMaterial[j].mDiffuseMap->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, mPreview, NULL, FALSE);
+					iter->second[i].mMaterial[j].mDiffuseMap->forceToSaveRawImage();
+				}
+			}
+		}
+	}
+
+	if(!is_paused)
+	{
+		unpause() ;
+	}
+}
+
 bool LLModelLoader::isNodeAJoint( domNode* pNode )
 {
 	if ( pNode->getName() == NULL)
@@ -1895,14 +1924,8 @@ LLImportMaterial LLModelLoader::profileToMaterial(domProfile_COMMON* material)
 								// we only support init_from now - embedded data will come later
 								domImage::domInit_from* init = image->getInit_from();
 								if (init)
-								{
-									std::string filename = cdom::uriToNativePath(init->getValue().str());
-
-									mat.mDiffuseMap = LLViewerTextureManager::getFetchedTextureFromUrl("file://" + filename, TRUE, LLViewerTexture::BOOST_PREVIEW);
-									mat.mDiffuseMap->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, this->mPreview, NULL, FALSE);
-
-									mat.mDiffuseMap->forceToSaveRawImage();
-									mat.mDiffuseMapFilename = filename;
+								{									
+									mat.mDiffuseMapFilename = cdom::uriToNativePath(init->getValue().str());
 									mat.mDiffuseMapLabel = getElementLabel(material);
 								}
 							}
@@ -2354,6 +2377,7 @@ void LLModelPreview::loadModelCallback(S32 lod)
 		return;
 	}
 
+	mModelLoader->loadTextures() ;
 	mModel[lod] = mModelLoader->mModelList;
 	mScene[lod] = mModelLoader->mScene;
 	mVertexBuffer[lod].clear();
@@ -3803,7 +3827,7 @@ BOOL LLModelPreview::render()
 							gGL.getTexUnit(0)->bind(instance.mMaterial[i].mDiffuseMap, true);
 							if (instance.mMaterial[i].mDiffuseMap->getDiscardLevel() > -1)
 							{
-								mTextureSet.insert(instance.mMaterial[i].mDiffuseMap);
+								mTextureSet.insert(instance.mMaterial[i].mDiffuseMap.get());
 							}
 						}
 					}
diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h
index 48263d493a..46c8a73cf2 100644
--- a/indra/newview/llfloatermodelpreview.h
+++ b/indra/newview/llfloatermodelpreview.h
@@ -96,6 +96,7 @@ public:
 
 	virtual void run();
 	
+	void loadTextures() ; //called in the main thread.
 	void processElement(daeElement* element);
 	std::vector<LLImportMaterial> getMaterials(LLModel* model, domInstance_geometry* instance_geo);
 	LLImportMaterial profileToMaterial(domProfile_COMMON* material);
@@ -327,7 +328,7 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex
 	std::map<LLPointer<LLModel>, std::vector<LLPointer<LLVertexBuffer> > > mPhysicsMesh;
 
 	LLMeshUploadThread::instance_list mUploadData;
-	std::set<LLPointer<LLViewerFetchedTexture> > mTextureSet;
+	std::set<LLViewerFetchedTexture* > mTextureSet;
 
 	//map of vertex buffers to models (one vertex buffer in vector per face in model
 	std::map<LLModel*, std::vector<LLPointer<LLVertexBuffer> > > mVertexBuffer[LLModel::NUM_LODS+1];
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index dd2dcffc28..d2f76eceb0 100755
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -1450,17 +1450,21 @@ void LLMeshUploadThread::DecompRequest::completed()
 	mThread->mHullMap[mBaseModel] = mHull[0];
 }
 
-void LLMeshUploadThread::run()
+//called in the main thread.
+void LLMeshUploadThread::preStart()
 {
-	mCurlRequest = new LLCurlRequest();
-
 	//build map of LLModel refs to instances for callbacks
 	for (instance_list::iterator iter = mInstanceList.begin(); iter != mInstanceList.end(); ++iter)
 	{
 		mInstance[iter->mModel].push_back(*iter);
 	}
+}
+
+void LLMeshUploadThread::run()
+{
+	mCurlRequest = new LLCurlRequest();	
 
-	std::set<LLPointer<LLViewerTexture> > textures;
+	std::set<LLViewerTexture* > textures;
 
 	//populate upload queue with relevant models
 	for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter)
@@ -1483,9 +1487,9 @@ void LLMeshUploadThread::run()
 				material_iter != instance.mMaterial.end(); ++material_iter)
 			{
 
-				if (textures.find(material_iter->mDiffuseMap) == textures.end())
+				if (textures.find(material_iter->mDiffuseMap.get()) == textures.end())
 				{
-					textures.insert(material_iter->mDiffuseMap);
+					textures.insert(material_iter->mDiffuseMap.get());
 					
 					LLTextureUploadData data(material_iter->mDiffuseMap.get(), material_iter->mDiffuseMapLabel);
 					uploadTexture(data);
@@ -2148,6 +2152,7 @@ S32 LLMeshRepository::update()
 	for (S32 i = 0; i < size; ++i)
 	{
 		mUploads.push_back(mUploadWaitList[i]);
+		mUploadWaitList[i]->preStart() ;
 		mUploadWaitList[i]->start() ;
 	}
 	mUploadWaitList.clear() ;
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index 8c9892b28f..eccb82b661 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -431,6 +431,7 @@ public:
 
 	bool finished() { return mFinished; }
 	virtual void run();
+	void preStart();
 	
 };
 
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 10126219f8..b5eadb6d25 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -834,7 +834,7 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time)
 	for (entries_list_t::iterator iter3 = entries.begin();
 		 iter3 != entries.end(); )
 	{
-		LLPointer<LLViewerFetchedTexture> imagep = *iter3++;
+		LLViewerFetchedTexture* imagep = *iter3++;
 		
 		bool fetching = imagep->updateFetch();
 		if (fetching)
-- 
cgit v1.2.3


From f1b7fce1db6cd7a8f312216baaa8fada931b2579 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Tue, 4 Jan 2011 16:28:40 -0700
Subject: a debug tool to detect LLPointer issues for SH-694: check if there
 are any other LLPointer issues in the mesh model uploading flow and fix them
 if exist. This debug tool is off by default. To turn it on, set
 LL_REF_COUNT_DEBUG to be 1 in the header file "llcommon/llrefcount.h".

---
 indra/llcommon/llrefcount.cpp | 110 ++++++++++++++++++++++++++++++++++++++++++
 indra/llcommon/llrefcount.h   |  20 +++++++-
 2 files changed, 128 insertions(+), 2 deletions(-)

diff --git a/indra/llcommon/llrefcount.cpp b/indra/llcommon/llrefcount.cpp
index 55d0c85cbd..e1876599fc 100644
--- a/indra/llcommon/llrefcount.cpp
+++ b/indra/llcommon/llrefcount.cpp
@@ -29,9 +29,25 @@
 
 #include "llerror.h"
 
+#if LL_REF_COUNT_DEBUG
+#include "llthread.h"
+#include "llapr.h"
+#endif
+
 LLRefCount::LLRefCount(const LLRefCount& other)
 :	mRef(0)
 {
+#if LL_REF_COUNT_DEBUG
+	if(gAPRPoolp)
+	{
+		mMutexp = new LLMutex(gAPRPoolp) ;
+	}
+	else
+	{
+		mMutexp = NULL ;
+	}
+	mCrashAtUnlock = FALSE ;
+#endif
 }
 
 LLRefCount& LLRefCount::operator=(const LLRefCount&)
@@ -43,6 +59,17 @@ LLRefCount& LLRefCount::operator=(const LLRefCount&)
 LLRefCount::LLRefCount() :
 	mRef(0)
 {
+#if LL_REF_COUNT_DEBUG
+	if(gAPRPoolp)
+	{
+		mMutexp = new LLMutex(gAPRPoolp) ;
+	}
+	else
+	{
+		mMutexp = NULL ;
+	}
+	mCrashAtUnlock = FALSE ;
+#endif
 }
 
 LLRefCount::~LLRefCount()
@@ -51,4 +78,87 @@ LLRefCount::~LLRefCount()
 	{
 		llerrs << "deleting non-zero reference" << llendl;
 	}
+
+#if LL_REF_COUNT_DEBUG
+	if(gAPRPoolp)
+	{
+		delete mMutexp ;
+	}
+#endif
 }
+
+#if LL_REF_COUNT_DEBUG
+void LLRefCount::ref() const
+{ 
+	if(mMutexp)
+	{
+		if(mMutexp->isLocked()) 
+		{
+			mCrashAtUnlock = TRUE ;
+			llerrs << "the mutex is locked by the thread: " << mLockedThreadID 
+				<< " Current thread: " << LLThread::currentID() << llendl ;
+		}
+
+		mMutexp->lock() ;
+		mLockedThreadID = LLThread::currentID() ;
+
+		mRef++; 
+
+		if(mCrashAtUnlock)
+		{
+			while(1); //crash here.
+		}
+		mMutexp->unlock() ;
+	}
+	else
+	{
+		mRef++; 
+	}
+} 
+
+S32 LLRefCount::unref() const
+{
+	if(mMutexp)
+	{
+		if(mMutexp->isLocked()) 
+		{
+			mCrashAtUnlock = TRUE ;
+			llerrs << "the mutex is locked by the thread: " << mLockedThreadID 
+				<< " Current thread: " << LLThread::currentID() << llendl ;
+		}
+
+		mMutexp->lock() ;
+		mLockedThreadID = LLThread::currentID() ;
+		
+		llassert(mRef >= 1);
+		if (0 == --mRef) 
+		{
+			if(mCrashAtUnlock)
+			{
+				while(1); //crash here.
+			}
+			mMutexp->unlock() ;
+
+			delete this; 
+			return 0;
+		}
+
+		if(mCrashAtUnlock)
+		{
+			while(1); //crash here.
+		}
+		mMutexp->unlock() ;
+		return mRef;
+	}
+	else
+	{
+		llassert(mRef >= 1);
+		if (0 == --mRef) 
+		{
+			delete this; 
+			return 0;
+		}
+		return mRef;
+	}
+}	
+#endif
diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h
index 19f008b15c..693c1c4b83 100644
--- a/indra/llcommon/llrefcount.h
+++ b/indra/llcommon/llrefcount.h
@@ -28,6 +28,11 @@
 
 #include <boost/noncopyable.hpp>
 
+#define LL_REF_COUNT_DEBUG 0
+#if LL_REF_COUNT_DEBUG
+class LLMutex ;
+#endif
+
 //----------------------------------------------------------------------------
 // RefCount objects should generally only be accessed by way of LLPointer<>'s
 // see llthread.h for LLThreadSafeRefCount
@@ -43,12 +48,16 @@ protected:
 public:
 	LLRefCount();
 
-	void ref() const
+#if LL_REF_COUNT_DEBUG
+	void ref() const ;
+	S32 unref() const ;
+#else
+	inline void LLRefCount::ref() const
 	{ 
 		mRef++; 
 	} 
 
-	S32 unref() const
+	inline S32 LLRefCount::unref() const
 	{
 		llassert(mRef >= 1);
 		if (0 == --mRef) 
@@ -58,6 +67,7 @@ public:
 		}
 		return mRef;
 	}	
+#endif
 
 	//NOTE: when passing around a const LLRefCount object, this can return different results
 	// at different types, since mRef is mutable
@@ -68,6 +78,12 @@ public:
 
 private: 
 	mutable S32	mRef; 
+
+#if LL_REF_COUNT_DEBUG
+	LLMutex*  mMutexp ;
+	mutable U32  mLockedThreadID ;
+	mutable BOOL mCrashAtUnlock ; 
+#endif
 };
 
 #endif
-- 
cgit v1.2.3