From 897972636d0fdd0c6dc76e1a337bb43e1aa9bc0c Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Mon, 10 Oct 2011 16:31:56 -0600
Subject: [PATCH] fix for SH-2464: Crash on exit in
 LLPrivateMemoryPoolManager::freeMem

---
 indra/llcommon/llmemory.cpp | 41 +++++++++++++++++++++++++++++++++++--
 indra/llcommon/llmemory.h   |  1 +
 2 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index 8c02ad82908..7d340483b7c 100644
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -1773,6 +1773,7 @@ void LLPrivateMemoryPool::LLChunkHashElement::remove(LLPrivateMemoryPool::LLMemo
 //class LLPrivateMemoryPoolManager
 //--------------------------------------------------------------------
 LLPrivateMemoryPoolManager* LLPrivateMemoryPoolManager::sInstance = NULL ;
+std::vector<LLPrivateMemoryPool*> LLPrivateMemoryPoolManager::sDanglingPoolList ;
 
 LLPrivateMemoryPoolManager::LLPrivateMemoryPoolManager(BOOL enabled) 
 {
@@ -1797,7 +1798,7 @@ LLPrivateMemoryPoolManager::~LLPrivateMemoryPoolManager()
 		S32 k = 0 ;
 		for(mem_allocation_info_t::iterator iter = sMemAllocationTracker.begin() ; iter != sMemAllocationTracker.end() ; ++iter)
 		{
-			llinfos << k++ << ", " << iter->second << llendl ;
+			llinfos << k++ << ", " << (U32)iter->first << " : " << iter->second << llendl ;
 		}
 		sMemAllocationTracker.clear() ;
 	}
@@ -1817,7 +1818,17 @@ LLPrivateMemoryPoolManager::~LLPrivateMemoryPoolManager()
 	{
 		if(mPoolList[i])
 		{
-			delete mPoolList[i] ;
+			if(mPoolList[i]->isEmpty())
+			{
+				delete mPoolList[i] ;
+			}
+			else
+			{
+				//can not delete this pool because it has alloacted memory to be freed.
+				//move it to the dangling list.
+				sDanglingPoolList.push_back(mPoolList[i]) ;				
+			}
+
 			mPoolList[i] = NULL ;
 		}
 	}
@@ -1953,6 +1964,32 @@ void  LLPrivateMemoryPoolManager::freeMem(LLPrivateMemoryPool* poolp, void* addr
 	}
 	else
 	{
+		if(!sInstance) //the private memory manager is destroyed, try the dangling list
+		{
+			for(S32 i = 0 ; i < sDanglingPoolList.size(); i++)
+			{
+				if(sDanglingPoolList[i]->findChunk((char*)addr))
+				{
+					sDanglingPoolList[i]->freeMem(addr) ;
+					if(sDanglingPoolList[i]->isEmpty())
+					{
+						delete sDanglingPoolList[i] ;
+						
+						if(i < sDanglingPoolList.size() - 1)
+						{
+							sDanglingPoolList[i] = sDanglingPoolList[sDanglingPoolList.size() - 1] ;
+						}
+						sDanglingPoolList.pop_back() ;
+					}
+
+					addr = NULL ;
+					break ;
+				}
+			}
+		}
+
+		llassert_always(!addr) ; //addr should be release before hitting here!
+
 		free(addr) ;
 	}	
 }
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index db753f0d8ba..25e6c68e88f 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -399,6 +399,7 @@ class LL_COMMON_API LLPrivateMemoryPoolManager
 	std::vector<LLPrivateMemoryPool*> mPoolList ;
 	BOOL mPrivatePoolEnabled;
 
+	static std::vector<LLPrivateMemoryPool*> sDanglingPoolList ;
 public:
 	//debug and statistics info.
 	void updateStatistics() ;
-- 
GitLab