From b4766d2fde6b74c5a4a50cdde4373b5261a020e2 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Mon, 21 Nov 2011 14:42:21 -0700
Subject: fix for sh-2601: [crashhunters] crash in LLBufferArray::countAfter()
 sh-2602: [crashhunters] crash on exit in ~LLPumpIO()

---
 indra/llmessage/llcurl.cpp            | 356 +++++++++++++++++++++-------------
 indra/llmessage/llcurl.h              | 105 +++++++---
 indra/llmessage/llurlrequest.cpp      |   6 +-
 indra/newview/llappviewer.cpp         |   5 +
 indra/newview/llxmlrpctransaction.cpp |  16 +-
 5 files changed, 308 insertions(+), 180 deletions(-)

diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 330028c926..7f61e1ac04 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -86,9 +86,7 @@ S32 gCurlMultiCount = 0;
 std::vector<LLMutex*> LLCurl::sSSLMutex;
 std::string LLCurl::sCAPath;
 std::string LLCurl::sCAFile;
-
-bool LLCurl::sMultiThreaded = false;
-static U32 sMainThreadID = 0;
+LLCurlThread* LLCurl::sCurlThread = NULL ;
 
 void check_curl_code(CURLcode code)
 {
@@ -221,14 +219,11 @@ namespace boost
 
 std::set<CURL*> LLCurl::Easy::sFreeHandles;
 std::set<CURL*> LLCurl::Easy::sActiveHandles;
-LLMutex* LLCurl::Easy::sHandleMutex = NULL;
-LLMutex* LLCurl::Easy::sMultiMutex = NULL;
 
 //static
 CURL* LLCurl::Easy::allocEasyHandle()
 {
 	CURL* ret = NULL;
-	LLMutexLock lock(sHandleMutex);
 	if (sFreeHandles.empty())
 	{
 		ret = curl_easy_init();
@@ -256,8 +251,6 @@ void LLCurl::Easy::releaseEasyHandle(CURL* handle)
 		llerrs << "handle cannot be NULL!" << llendl;
 	}
 
-	LLMutexLock lock(sHandleMutex);
-	
 	if (sActiveHandles.find(handle) != sActiveHandles.end())
 	{
 		sActiveHandles.erase(handle);
@@ -521,23 +514,13 @@ void LLCurl::Easy::prepRequest(const std::string& url,
 ////////////////////////////////////////////////////////////////////////////
 
 LLCurl::Multi::Multi()
-	: LLThread("Curl Multi"),
-	  mQueued(0),
+	: mQueued(0),
 	  mErrorCount(0),
-	  mPerformState(PERFORM_STATE_READY)
+	  mState(STATE_READY),
+	  mDead(FALSE),
+	  mMutexp(NULL),
+	  mDeletionMutexp(NULL)
 {
-	mQuitting = false;
-
-	mThreaded = LLCurl::sMultiThreaded && LLThread::currentID() == sMainThreadID;
-	if (mThreaded)
-	{
-		mSignal = new LLCondition(NULL);
-	}
-	else
-	{
-		mSignal = NULL;
-	}
-
 	mCurlMultiHandle = curl_multi_init();
 	if (!mCurlMultiHandle)
 	{
@@ -545,22 +528,20 @@ LLCurl::Multi::Multi()
 		mCurlMultiHandle = curl_multi_init();
 	}
 	
-	llassert_always(mCurlMultiHandle);
-	++gCurlMultiCount;
-}
-
-LLCurl::Multi::~Multi()
-{
-	llassert(isStopped());
+	llassert_always(mCurlMultiHandle);	
 
-	if (LLCurl::sMultiThreaded)
+	if(LLCurl::getCurlThread()->getThreaded())
 	{
-		LLCurl::Easy::sMultiMutex->lock();
+		mMutexp = new LLMutex(NULL) ;
+		mDeletionMutexp = new LLMutex(NULL) ;
 	}
+	LLCurl::getCurlThread()->addMulti(this) ;
 
-	delete mSignal;
-	mSignal = NULL;
+	++gCurlMultiCount;
+}
 
+LLCurl::Multi::~Multi()
+{
 	// Clean up active
 	for(easy_active_list_t::iterator iter = mEasyActiveList.begin();
 		iter != mEasyActiveList.end(); ++iter)
@@ -577,75 +558,149 @@ LLCurl::Multi::~Multi()
 	mEasyFreeList.clear();
 
 	check_curl_multi_code(curl_multi_cleanup(mCurlMultiHandle));
+
+	delete mMutexp ;
+	mMutexp = NULL ;
+	delete mDeletionMutexp ;
+	mDeletionMutexp = NULL ;
+
 	--gCurlMultiCount;
+}
 
-	if (LLCurl::sMultiThreaded)
+void LLCurl::Multi::lock()
+{
+	if(mMutexp)
 	{
-		LLCurl::Easy::sMultiMutex->unlock();
+		mMutexp->lock() ;
 	}
 }
 
-CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue)
+void LLCurl::Multi::unlock()
 {
-	CURLMsg* curlmsg = curl_multi_info_read(mCurlMultiHandle, msgs_in_queue);
-	return curlmsg;
+	if(mMutexp)
+	{
+		mMutexp->unlock() ;
+	}
 }
 
-void LLCurl::Multi::perform()
+void LLCurl::Multi::markDead()
 {
-	if (mThreaded)
+	if(mDeletionMutexp)
 	{
-		if (mPerformState == PERFORM_STATE_READY)
-		{
-			mSignal->signal();
-		}
+		mDeletionMutexp->lock() ;
 	}
-	else
+
+	mDead = TRUE ;
+
+	if(mDeletionMutexp)
+	{
+		mDeletionMutexp->unlock() ;
+	}
+}
+
+void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state)
+{
+	lock() ;
+	mState = state ;
+	if(mState == STATE_READY)
 	{
-		doPerform();
+		LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_NORMAL) ;
 	}
+	unlock() ;
 }
 
-void LLCurl::Multi::run()
+LLCurl::Multi::ePerformState LLCurl::Multi::getState()
 {
-	llassert(mThreaded);
+	ePerformState state ;
+
+	lock() ;
+	state = mState ;
+	unlock() ;
+
+	return state ;
+}
+	
+bool LLCurl::Multi::isCompleted() 
+{
+	return STATE_COMPLETED == getState() ;
+}
 
-	while (!mQuitting)
+bool LLCurl::Multi::waitToComplete()
+{
+	if(!mMutexp) //not threaded
 	{
-		mSignal->wait();
-		mPerformState = PERFORM_STATE_PERFORMING;
-		if (!mQuitting)
-		{
-			LLMutexLock lock(LLCurl::Easy::sMultiMutex);
-			doPerform();
-		}
+		doPerform() ;
+		return true ;
+	}
+
+	bool completed ;
+
+	lock() ;
+	completed = (STATE_COMPLETED == mState) ;
+	if(!completed)
+	{
+		LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ;
 	}
+	unlock() ;
+
+	return completed;
 }
 
-void LLCurl::Multi::doPerform()
+CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue)
 {
-	S32 q = 0;
-	for (S32 call_count = 0;
-			call_count < MULTI_PERFORM_CALL_REPEAT;
-			call_count += 1)
+	CURLMsg* curlmsg = curl_multi_info_read(mCurlMultiHandle, msgs_in_queue);
+	return curlmsg;
+}
+
+//return true if dead
+bool LLCurl::Multi::doPerform()
+{
+	if(mDeletionMutexp)
+	{
+		mDeletionMutexp->lock() ;
+	}
+	bool dead = mDead ;
+
+	if(mDead)
 	{
-		CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q);
-		if (CURLM_CALL_MULTI_PERFORM != code || q == 0)
+		setState(STATE_COMPLETED);
+		mQueued = 0 ;
+	}
+	else if(getState() != STATE_COMPLETED)
+	{		
+		setState(STATE_PERFORMING);
+
+		S32 q = 0;
+		for (S32 call_count = 0;
+				call_count < MULTI_PERFORM_CALL_REPEAT;
+				call_count++)
 		{
-			check_curl_multi_code(code);
-			break;
+			CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q);
+			if (CURLM_CALL_MULTI_PERFORM != code || q == 0)
+			{
+				check_curl_multi_code(code);
+			
+				break;
+			}
 		}
-	
+
+		mQueued = q;	
+		setState(STATE_COMPLETED) ;
 	}
-	mQueued = q;
-	mPerformState = PERFORM_STATE_COMPLETED;
+
+	if(mDeletionMutexp)
+	{
+		mDeletionMutexp->unlock() ;
+	}
+
+	return dead ;
 }
 
 S32 LLCurl::Multi::process()
 {
-	perform();
+	waitToComplete() ;
 
-	if (mPerformState != PERFORM_STATE_COMPLETED)
+	if (getState() != STATE_COMPLETED)
 	{
 		return 0;
 	}
@@ -681,7 +736,8 @@ S32 LLCurl::Multi::process()
 		}
 	}
 
-	mPerformState = PERFORM_STATE_READY;
+	setState(STATE_READY);
+
 	return processed;
 }
 
@@ -739,6 +795,75 @@ void LLCurl::Multi::removeEasy(Easy* easy)
 	easyFree(easy);
 }
 
+//------------------------------------------------------------
+//LLCurlThread
+LLCurlThread::CurlRequest::CurlRequest(handle_t handle, LLCurl::Multi* multi) :
+	LLQueuedThread::QueuedRequest(handle, LLQueuedThread::PRIORITY_NORMAL, FLAG_AUTO_COMPLETE),
+	mMulti(multi)
+{	
+}
+
+LLCurlThread::CurlRequest::~CurlRequest()
+{	
+	if(mMulti)
+	{
+		delete mMulti ;
+		mMulti = NULL ;
+	}
+}
+
+bool LLCurlThread::CurlRequest::processRequest()
+{
+	bool completed = true ;
+	if(mMulti)
+	{
+		completed = mMulti->doPerform() ;
+		setPriority(LLQueuedThread::PRIORITY_LOW) ;
+	}
+
+	return completed ;
+}
+
+void LLCurlThread::CurlRequest::finishRequest(bool completed)
+{
+	delete mMulti ;
+	mMulti = NULL ;
+}
+	
+LLCurlThread::LLCurlThread(bool threaded) :
+	LLQueuedThread("curlthread", threaded)
+{
+}
+	
+//virtual 
+LLCurlThread::~LLCurlThread() 
+{
+}
+
+S32 LLCurlThread::update(U32 max_time_ms)
+{	
+	return LLQueuedThread::update(max_time_ms);
+}
+
+void LLCurlThread::addMulti(LLCurl::Multi* multi)
+{
+	multi->mHandle = generateHandle() ;
+
+	CurlRequest* req = new CurlRequest(multi->mHandle, multi) ;
+
+	if (!addRequest(req))
+	{
+		llwarns << "curl request added when the thread is quitted" << llendl;
+	}
+}
+	
+void LLCurlThread::deleteMulti(LLCurl::Multi* multi)
+{
+	multi->markDead() ;
+}
+
+//------------------------------------------------------------
+
 //static
 std::string LLCurl::strerror(CURLcode errorcode)
 {
@@ -753,39 +878,23 @@ LLCurlRequest::LLCurlRequest() :
 	mActiveMulti(NULL),
 	mActiveRequestCount(0)
 {
-	mThreadID = LLThread::currentID();
 	mProcessing = FALSE;
 }
 
 LLCurlRequest::~LLCurlRequest()
 {
-	llassert_always(mThreadID == LLThread::currentID());
-
 	//stop all Multi handle background threads
 	for (curlmulti_set_t::iterator iter = mMultiSet.begin(); iter != mMultiSet.end(); ++iter)
 	{
-		LLCurl::Multi* multi = *iter;
-		multi->mQuitting = true;
-		if (multi->mThreaded)
-		{
-			while (!multi->isStopped())
-			{
-				multi->mSignal->signal();
-				apr_sleep(1000);
-			}
-		}
+		LLCurl::getCurlThread()->deleteMulti(*iter) ;
 	}
-	for_each(mMultiSet.begin(), mMultiSet.end(), DeletePointer());
+	mMultiSet.clear() ;
 }
 
 void LLCurlRequest::addMulti()
 {
-	llassert_always(mThreadID == LLThread::currentID());
 	LLCurl::Multi* multi = new LLCurl::Multi();
-	if (multi->mThreaded)
-	{
-		multi->start();
-	}
+	
 	mMultiSet.insert(multi);
 	mActiveMulti = multi;
 	mActiveRequestCount = 0;
@@ -901,7 +1010,6 @@ bool LLCurlRequest::post(const std::string& url,
 // Note: call once per frame
 S32 LLCurlRequest::process()
 {
-	llassert_always(mThreadID == LLThread::currentID());
 	S32 res = 0;
 
 	mProcessing = TRUE;
@@ -915,17 +1023,7 @@ S32 LLCurlRequest::process()
 		if (multi != mActiveMulti && tres == 0 && multi->mQueued == 0)
 		{
 			mMultiSet.erase(curiter);
-			multi->mQuitting = true;
-			if (multi->mThreaded)
-			{
-				while (!multi->isStopped())
-				{
-					multi->mSignal->signal();
-					apr_sleep(1000);
-				}
-			}
-
-			delete multi;
+			LLCurl::getCurlThread()->deleteMulti(multi);
 		}
 	}
 	mProcessing = FALSE;
@@ -934,7 +1032,6 @@ S32 LLCurlRequest::process()
 
 S32 LLCurlRequest::getQueued()
 {
-	llassert_always(mThreadID == LLThread::currentID());
 	S32 queued = 0;
 	for (curlmulti_set_t::iterator iter = mMultiSet.begin();
 		 iter != mMultiSet.end(); )
@@ -942,7 +1039,7 @@ S32 LLCurlRequest::getQueued()
 		curlmulti_set_t::iterator curiter = iter++;
 		LLCurl::Multi* multi = *curiter;
 		queued += multi->mQueued;
-		if (multi->mPerformState != LLCurl::Multi::PERFORM_STATE_READY)
+		if (multi->getState() != LLCurl::Multi::STATE_READY)
 		{
 			++queued;
 		}
@@ -959,10 +1056,7 @@ LLCurlEasyRequest::LLCurlEasyRequest()
 	  mResultReturned(false)
 {
 	mMulti = new LLCurl::Multi();
-	if (mMulti->mThreaded)
-	{
-		mMulti->start();
-	}
+	
 	mEasy = mMulti->allocEasy();
 	if (mEasy)
 	{
@@ -975,16 +1069,7 @@ LLCurlEasyRequest::LLCurlEasyRequest()
 
 LLCurlEasyRequest::~LLCurlEasyRequest()
 {
-	mMulti->mQuitting = true;
-	if (mMulti->mThreaded)
-	{
-		while (!mMulti->isStopped())
-		{
-			mMulti->mSignal->signal();
-			apr_sleep(1000);
-		}
-	}
-	delete mMulti;
+	LLCurl::getCurlThread()->deleteMulti(mMulti) ;
 }
 	
 void LLCurlEasyRequest::setopt(CURLoption option, S32 value)
@@ -1080,19 +1165,14 @@ void LLCurlEasyRequest::requestComplete()
 	}
 }
 
-void LLCurlEasyRequest::perform()
-{
-	mMulti->perform();
-}
-
 // Usage: Call getRestult until it returns false (no more messages)
 bool LLCurlEasyRequest::getResult(CURLcode* result, LLCurl::TransferInfo* info)
 {
-	if (mMulti->mPerformState != LLCurl::Multi::PERFORM_STATE_COMPLETED)
+	if (!mMulti->isCompleted())
 	{ //we're busy, try again later
 		return false;
 	}
-	mMulti->mPerformState = LLCurl::Multi::PERFORM_STATE_READY;
+	mMulti->setState(LLCurl::Multi::STATE_READY) ;
 
 	if (!mEasy)
 	{
@@ -1180,8 +1260,6 @@ unsigned long LLCurl::ssl_thread_id(void)
 
 void LLCurl::initClass(bool multi_threaded)
 {
-	sMainThreadID = LLThread::currentID();
-	sMultiThreaded = multi_threaded;
 	// Do not change this "unless you are familiar with and mean to control 
 	// internal operations of libcurl"
 	// - http://curl.haxx.se/libcurl/c/curl_global_init.html
@@ -1189,9 +1267,6 @@ void LLCurl::initClass(bool multi_threaded)
 
 	check_curl_code(code);
 	
-	Easy::sHandleMutex = new LLMutex(NULL);
-	Easy::sMultiMutex = new LLMutex(NULL);
-
 #if SAFE_SSL
 	S32 mutex_count = CRYPTO_num_locks();
 	for (S32 i=0; i<mutex_count; i++)
@@ -1201,20 +1276,29 @@ void LLCurl::initClass(bool multi_threaded)
 	CRYPTO_set_id_callback(&LLCurl::ssl_thread_id);
 	CRYPTO_set_locking_callback(&LLCurl::ssl_locking_callback);
 #endif
+
+	sCurlThread = new LLCurlThread(multi_threaded) ;
 }
 
 void LLCurl::cleanupClass()
 {
+	//shut down curl thread
+	while(1)
+	{
+		if(!sCurlThread->update(1)) //finish all tasks
+		{
+			break ;
+		}
+	}
+	sCurlThread->shutdown() ;
+	delete sCurlThread ;
+	sCurlThread = NULL ;
+
 #if SAFE_SSL
 	CRYPTO_set_locking_callback(NULL);
 	for_each(sSSLMutex.begin(), sSSLMutex.end(), DeletePointer());
 #endif
 
-	delete Easy::sHandleMutex;
-	Easy::sHandleMutex = NULL;
-	delete Easy::sMultiMutex;
-	Easy::sMultiMutex = NULL;
-
 	for (std::set<CURL*>::iterator iter = Easy::sFreeHandles.begin(); iter != Easy::sFreeHandles.end(); ++iter)
 	{
 		CURL* curl = *iter;
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index 87de202717..23a6ca67e3 100755
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -42,8 +42,10 @@
 #include "lliopipe.h"
 #include "llsd.h"
 #include "llthread.h"
+#include "llqueuedthread.h"
 
 class LLMutex;
+class LLCurlThread;
 
 // For whatever reason, this is not typedef'd in curl.h
 typedef size_t (*curl_header_callback)(void *ptr, size_t size, size_t nmemb, void *stream);
@@ -56,8 +58,6 @@ public:
 	class Easy;
 	class Multi;
 
-	static bool sMultiThreaded;
-
 	struct TransferInfo
 	{
 		TransferInfo() : mSizeDownload(0.0), mTotalTime(0.0), mSpeedDownload(0.0) {}
@@ -181,10 +181,12 @@ public:
 	static void ssl_locking_callback(int mode, int type, const char *file, int line);
 	static unsigned long ssl_thread_id(void);
 
+	static LLCurlThread* getCurlThread() { return sCurlThread ;}
 private:
 	static std::string sCAPath;
 	static std::string sCAFile;
 	static const unsigned int MAX_REDIRECTS;
+	static LLCurlThread* sCurlThread;
 };
 
 class LLCurl::Easy
@@ -216,7 +218,7 @@ public:
 	U32 report(CURLcode);
 	void getTransferInfo(LLCurl::TransferInfo* info);
 
-	void prepRequest(const std::string& url, const std::vector<std::string>& headers, ResponderPtr, S32 time_out = 0, bool post = false);
+	void prepRequest(const std::string& url, const std::vector<std::string>& headers, LLCurl::ResponderPtr, S32 time_out = 0, bool post = false);
 
 	const char* getErrorBuffer();
 
@@ -247,64 +249,105 @@ private:
 	// Note: char*'s not strings since we pass pointers to curl
 	std::vector<char*>	mStrings;
 
-	ResponderPtr		mResponder;
+	LLCurl::ResponderPtr		mResponder;
 
 	static std::set<CURL*> sFreeHandles;
 	static std::set<CURL*> sActiveHandles;
-	static LLMutex* sHandleMutex;
-	static LLMutex* sMultiMutex;
 };
 
-class LLCurl::Multi : public LLThread
+class LLCurl::Multi
 {
 	LOG_CLASS(Multi);
+
+	friend class LLCurlThread ;
+
+private:
+	~Multi();
+
+	void markDead() ;
+	bool doPerform();
+
 public:
 
 	typedef enum
 	{
-		PERFORM_STATE_READY=0,
-		PERFORM_STATE_PERFORMING=1,
-		PERFORM_STATE_COMPLETED=2
+		STATE_READY=0,
+		STATE_PERFORMING=1,
+		STATE_COMPLETED=2
 	} ePerformState;
 
-	Multi();
-	~Multi();
+	Multi();	
 
-	Easy* allocEasy();
-	bool addEasy(Easy* easy);
+	LLCurl::Easy* allocEasy();
+	bool addEasy(LLCurl::Easy* easy);	
+	void removeEasy(LLCurl::Easy* easy);
 	
-	void removeEasy(Easy* easy);
+	void lock() ;
+	void unlock() ;
+
+	void setState(ePerformState state) ;
+	ePerformState getState() ;
+	bool isCompleted() ;
+
+	bool waitToComplete() ;
 
 	S32 process();
-	void perform();
-	void doPerform();
 	
-	virtual void run();
-
 	CURLMsg* info_read(S32* msgs_in_queue);
 
 	S32 mQueued;
 	S32 mErrorCount;
 	
-	S32 mPerformState;
-
-	LLCondition* mSignal;
-	bool mQuitting;
-	bool mThreaded;
-
 private:
-	void easyFree(Easy*);
+	void easyFree(LLCurl::Easy*);
 	
 	CURLM* mCurlMultiHandle;
 
-	typedef std::set<Easy*> easy_active_list_t;
+	typedef std::set<LLCurl::Easy*> easy_active_list_t;
 	easy_active_list_t mEasyActiveList;
-	typedef std::map<CURL*, Easy*> easy_active_map_t;
+	typedef std::map<CURL*, LLCurl::Easy*> easy_active_map_t;
 	easy_active_map_t mEasyActiveMap;
-	typedef std::set<Easy*> easy_free_list_t;
+	typedef std::set<LLCurl::Easy*> easy_free_list_t;
 	easy_free_list_t mEasyFreeList;
+
+	LLQueuedThread::handle_t mHandle ;
+	ePerformState mState;
+
+	BOOL mDead ;
+	LLMutex* mMutexp ;
+	LLMutex* mDeletionMutexp ;
 };
 
+class LLCurlThread : public LLQueuedThread
+{
+public:
+
+	class CurlRequest : public LLQueuedThread::QueuedRequest
+	{
+	protected:
+		virtual ~CurlRequest(); // use deleteRequest()
+		
+	public:
+		CurlRequest(handle_t handle, LLCurl::Multi* multi);
+
+		/*virtual*/ bool processRequest();
+		/*virtual*/ void finishRequest(bool completed);
+
+	private:
+		// input
+		LLCurl::Multi* mMulti;
+	};
+	
+public:
+	LLCurlThread(bool threaded = true) ;
+	virtual ~LLCurlThread() ;
+
+	S32 update(U32 max_time_ms);
+
+	void addMulti(LLCurl::Multi* multi) ;
+	void deleteMulti(LLCurl::Multi* multi) ;
+} ;
+
 namespace boost
 {
 	void intrusive_ptr_add_ref(LLCurl::Responder* p);
@@ -339,7 +382,6 @@ private:
 	LLCurl::Multi* mActiveMulti;
 	S32 mActiveRequestCount;
 	BOOL mProcessing;
-	U32 mThreadID; // debug
 };
 
 class LLCurlEasyRequest
@@ -357,9 +399,10 @@ public:
 	void slist_append(const char* str);
 	void sendRequest(const std::string& url);
 	void requestComplete();
-	void perform();
 	bool getResult(CURLcode* result, LLCurl::TransferInfo* info = NULL);
 	std::string getErrorString();
+	bool isCompleted() {return mMulti->isCompleted() ;}
+	bool wait() { return mMulti->waitToComplete(); }
 
 	LLCurl::Easy* getEasy() const { return mEasy; }
 
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index fa03bb7512..a3a2b2b1b8 100644
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -170,6 +170,7 @@ LLURLRequest::~LLURLRequest()
 {
 	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
 	delete mDetail;
+	mDetail = NULL ;
 }
 
 void LLURLRequest::setURL(const std::string& url)
@@ -344,7 +345,10 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
 		static LLFastTimer::DeclareTimer FTM_URL_PERFORM("Perform");
 		{
 			LLFastTimer t(FTM_URL_PERFORM);
-			mDetail->mCurlRequest->perform();
+			if(!mDetail->mCurlRequest->wait())
+			{
+				return status ;
+			}
 		}
 
 		while(1)
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index c937f604fc..8b7108e1e2 100755
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1417,6 +1417,11 @@ bool LLAppViewer::mainLoop()
 					}
 				}
 				gMeshRepo.update() ;
+				
+				if(!LLCurl::getCurlThread()->update(1))
+				{
+					LLCurl::getCurlThread()->pause() ; //nothing in the curl thread.
+				}
 
 				if(!total_work_pending) //pause texture fetching threads if nothing to process.
 				{
diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index f483ba5af8..920a9a3752 100644
--- a/indra/newview/llxmlrpctransaction.cpp
+++ b/indra/newview/llxmlrpctransaction.cpp
@@ -382,19 +382,11 @@ bool LLXMLRPCTransaction::Impl::process()
 			// continue onward
 		}
 	}
-	
-	//const F32 MAX_PROCESSING_TIME = 0.05f;
-	//LLTimer timer;
-
-	mCurlRequest->perform();
-
-	/*while (mCurlRequest->perform() > 0)
+		
+	if(!mCurlRequest->wait())
 	{
-		if (timer.getElapsedTimeF32() >= MAX_PROCESSING_TIME)
-		{
-			return false;
-		}
-	}*/
+		return false ;
+	}
 
 	while(1)
 	{
-- 
cgit v1.2.3


From 1dd24cfcf85f4807410bb8d5320a692e2d7e121c Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 21 Nov 2011 17:40:12 -0500
Subject: SH-2614 FIX, SH-2684 FIX - fixed buggy state management in
 onPhysicsUseLOD

---
 indra/newview/llfloatermodelpreview.cpp | 38 ++++++++++++++++-----------------
 1 file changed, 19 insertions(+), 19 deletions(-)
 mode change 100644 => 100755 indra/newview/llfloatermodelpreview.cpp

diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
old mode 100644
new mode 100755
index 881f087d7b..49e29e7447
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -995,38 +995,38 @@ void LLFloaterModelPreview::onPhysicsBrowse(LLUICtrl* ctrl, void* userdata)
 //static
 void LLFloaterModelPreview::onPhysicsUseLOD(LLUICtrl* ctrl, void* userdata)
 {
-	S32 num_modes = 4;
-	S32 which_mode = 3;
-	static S32 previous_mode = which_mode;
+	S32 num_lods = 4;
+	S32 which_mode;
 
 	LLCtrlSelectionInterface* iface = sInstance->childGetSelectionInterface("physics_lod_combo");
 	if (iface)
 	{
 		which_mode = iface->getFirstSelectedIndex();
 	}
+	else
+	{
+		llwarns << "no iface" << llendl;
+		return;
+	}
 
-	S32 file_mode = iface->getItemCount() - 1;
-	bool file_browse = which_mode == file_mode;
-	bool lod_to_file = file_browse && (previous_mode != file_mode);
-	bool file_to_lod = !file_browse && (previous_mode == file_mode);
-
-	if (!lod_to_file)
+	if (which_mode <= 0)
 	{
-		which_mode = num_modes - which_mode;
-		sInstance->mModelPreview->setPhysicsFromLOD(which_mode);
+		llwarns << "which_mode out of range, " << which_mode << llendl;
 	}
 
-	if (lod_to_file || file_to_lod)
+	S32 file_mode = iface->getItemCount() - 1;
+	if (which_mode < file_mode)
 	{
-		LLModelPreview *model_preview = sInstance->mModelPreview;
-		if (model_preview)
-		{
-			model_preview->refresh();
-			model_preview->updateStatusMessages();
-		}
+		S32 which_lod = num_lods - which_mode;
+		sInstance->mModelPreview->setPhysicsFromLOD(which_lod);
 	}
 
-	previous_mode = which_mode;
+	LLModelPreview *model_preview = sInstance->mModelPreview;
+	if (model_preview)
+	{
+		model_preview->refresh();
+		model_preview->updateStatusMessages();
+	}
 }
 
 //static 
-- 
cgit v1.2.3


From 9850e09f7663558070bca6353a7da806a53f4441 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Tue, 22 Nov 2011 11:51:49 -0700
Subject: trivial: update the memory pool log info to the latest.

---
 indra/llcommon/llmemory.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index bb7998c0a8..3b9758f996 100644
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -159,6 +159,7 @@ void LLMemory::logMemoryInfo(BOOL update)
 	if(update)
 	{
 		updateMemoryInfo() ;
+		LLPrivateMemoryPoolManager::getInstance()->updateStatistics() ;
 	}
 
 	llinfos << "Current allocated physical memory(KB): " << sAllocatedMemInKB << llendl ;
-- 
cgit v1.2.3


From be3c6747a88d8bbb2c6b87c9eb97b14a42b90ae7 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Tue, 22 Nov 2011 11:53:44 -0700
Subject: remove redundant memory allocation for sh-2651: [crashhunters] Crash
 after google translate failure

---
 indra/llxml/llxmlnode.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp
index 9f1e249ddd..4362c88c4e 100644
--- a/indra/llxml/llxmlnode.cpp
+++ b/indra/llxml/llxmlnode.cpp
@@ -1277,7 +1277,7 @@ bool LLXMLNode::getAttribute(const LLStringTableEntry* name, LLXMLNodePtr& node,
 	{
 		return mDefault->getAttribute(name, node, FALSE);
 	}
-	node = new LLXMLNode();
+	
 	return false;
 }
 
-- 
cgit v1.2.3


From 2851cd519338ef4a1fde15da8d4015ab4380d6cb Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Mon, 28 Nov 2011 11:33:49 -0700
Subject: a try fix for sh-2651: [crashhunters] Crash after google translate
 failure and sh-2658: crash in LLPluginMessage::parse

---
 indra/llprimitive/llvolumexml.cpp | 19 +++++++++++--------
 indra/llprimitive/llvolumexml.h   |  6 +++---
 indra/llui/llui.cpp               |  7 +++++--
 indra/llxml/llxmlnode.cpp         |  8 ++++----
 indra/llxuixml/llxuiparser.cpp    |  1 +
 indra/newview/llvoicevivox.cpp    |  1 -
 6 files changed, 24 insertions(+), 18 deletions(-)

diff --git a/indra/llprimitive/llvolumexml.cpp b/indra/llprimitive/llvolumexml.cpp
index f4f9d4d713..bf2297a029 100644
--- a/indra/llprimitive/llvolumexml.cpp
+++ b/indra/llprimitive/llvolumexml.cpp
@@ -34,9 +34,9 @@
 
 //============================================================================
 
-LLXMLNode *LLVolumeXml::exportProfileParams(const LLProfileParams* params)
+LLPointer<LLXMLNode> LLVolumeXml::exportProfileParams(const LLProfileParams* params)
 {
-	LLXMLNode *ret = new LLXMLNode("profile", FALSE);
+	LLPointer<LLXMLNode> ret = new LLXMLNode("profile", FALSE);
 
 	ret->createChild("curve_type", TRUE)->setByteValue(1, &params->getCurveType());
 	ret->createChild("interval", FALSE)->setFloatValue(2, &params->getBegin());
@@ -46,9 +46,9 @@ LLXMLNode *LLVolumeXml::exportProfileParams(const LLProfileParams* params)
 }
 
 
-LLXMLNode *LLVolumeXml::exportPathParams(const LLPathParams* params)
+LLPointer<LLXMLNode> LLVolumeXml::exportPathParams(const LLPathParams* params)
 {
-	LLXMLNode *ret = new LLXMLNode("path", FALSE); 
+	LLPointer<LLXMLNode> ret = new LLXMLNode("path", FALSE); 
 	ret->createChild("curve_type", TRUE)->setByteValue(1, &params->getCurveType());
 	ret->createChild("interval", FALSE)->setFloatValue(2, &params->getBegin());
 	ret->createChild("scale", FALSE)->setFloatValue(2, params->getScale().mV);
@@ -63,12 +63,15 @@ LLXMLNode *LLVolumeXml::exportPathParams(const LLPathParams* params)
 }
 
 
-LLXMLNode *LLVolumeXml::exportVolumeParams(const LLVolumeParams* params)
+LLPointer<LLXMLNode> LLVolumeXml::exportVolumeParams(const LLVolumeParams* params)
 {
-	LLXMLNode *ret = new LLXMLNode("shape", FALSE);
+	LLPointer<LLXMLNode> ret = new LLXMLNode("shape", FALSE);
 	
-	exportPathParams(&params->getPathParams())->setParent(ret);
-	exportProfileParams(&params->getProfileParams())->setParent(ret);
+	LLPointer<LLXMLNode> node ;
+	node = exportPathParams(&params->getPathParams()) ;
+	node->setParent(ret);
+	node = exportProfileParams(&params->getProfileParams()) ;
+	node->setParent(ret);
 
 	return ret;
 }
diff --git a/indra/llprimitive/llvolumexml.h b/indra/llprimitive/llvolumexml.h
index 5e79205d9a..9d4d989475 100644
--- a/indra/llprimitive/llvolumexml.h
+++ b/indra/llprimitive/llvolumexml.h
@@ -34,11 +34,11 @@
 class LLVolumeXml
 {
 public:
-	static LLXMLNode* exportProfileParams(const LLProfileParams* params);
+	static LLPointer<LLXMLNode> exportProfileParams(const LLProfileParams* params);
 
-	static LLXMLNode* exportPathParams(const LLPathParams* params);
+	static LLPointer<LLXMLNode> exportPathParams(const LLPathParams* params);
 
-	static LLXMLNode* exportVolumeParams(const LLVolumeParams* params);
+	static LLPointer<LLXMLNode> exportVolumeParams(const LLVolumeParams* params);
 };
 
 #endif // LL_LLVOLUMEXML_H
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index 79ad99a770..69461ec099 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -1823,9 +1823,12 @@ void LLUI::setupPaths()
 	LLXMLNodePtr root;
 	BOOL success  = LLXMLNode::parseFile(filename, root, NULL);
 	Paths paths;
-	LLXUIParser parser;
-	parser.readXUI(root, paths, filename);
 
+	if(success)
+	{
+		LLXUIParser parser;
+		parser.readXUI(root, paths, filename);
+	}
 	sXUIPaths.clear();
 	
 	if (success && paths.validateBlock())
diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp
index 4362c88c4e..2b4a0fc2a1 100644
--- a/indra/llxml/llxmlnode.cpp
+++ b/indra/llxml/llxmlnode.cpp
@@ -693,7 +693,7 @@ bool LLXMLNode::parseFile(const std::string& filename, LLXMLNodePtr& node, LLXML
 	LLFILE* fp = LLFile::fopen(filename, "rb");		/* Flawfinder: ignore */
 	if (fp == NULL)
 	{
-		node = new LLXMLNode();
+		node = NULL ;
 		return false;
 	}
 	fseek(fp, 0, SEEK_END);
@@ -746,7 +746,7 @@ bool LLXMLNode::parseBuffer(
 	{
 		llwarns << "Parse failure - wrong number of top-level nodes xml."
 				<< llendl;
-		node = new LLXMLNode();
+		node = NULL ;
 		return false;
 	}
 
@@ -805,7 +805,7 @@ bool LLXMLNode::parseStream(
 	{
 		llwarns << "Parse failure - wrong number of top-level nodes xml."
 				<< llendl;
-		node = new LLXMLNode();
+		node = NULL;
 		return false;
 	}
 
@@ -1206,7 +1206,7 @@ bool LLXMLNode::getChild(const LLStringTableEntry* name, LLXMLNodePtr& node, BOO
 	{
 		return mDefault->getChild(name, node, FALSE);
 	}
-	node = new LLXMLNode();
+	node = NULL;
 	return false;
 }
 
diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp
index 878f992178..5a525f84a8 100644
--- a/indra/llxuixml/llxuiparser.cpp
+++ b/indra/llxuixml/llxuiparser.cpp
@@ -1247,6 +1247,7 @@ bool LLSimpleXUIParser::readXUI(const std::string& filename, LLInitParam::BaseBl
 	if( !file.isOpen() )
 	{
 		LL_WARNS("ReadXUI") << "Unable to open file " << filename << LL_ENDL;
+		XML_ParserFree( mParser );
 		return false;
 	}
 
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 8ecf4a80b7..2d7437f4f3 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -7020,7 +7020,6 @@ void LLVivoxVoiceClient::captureBufferPlayStopSendMessage()
 
 LLVivoxProtocolParser::LLVivoxProtocolParser()
 {
-	parser = NULL;
 	parser = XML_ParserCreate(NULL);
 	
 	reset();
-- 
cgit v1.2.3


From 3fc4c14464c1b8152108a5332b754d5b2671e54d Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Tue, 29 Nov 2011 16:18:50 -0700
Subject: fix a mac build error: a friend declaration issue.

---
 indra/llmessage/llcurl.cpp | 32 ++++++++++++++++++++++----------
 indra/llmessage/llcurl.h   | 10 ++++++++--
 2 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 7f61e1ac04..7ca25d07fc 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -797,9 +797,10 @@ void LLCurl::Multi::removeEasy(Easy* easy)
 
 //------------------------------------------------------------
 //LLCurlThread
-LLCurlThread::CurlRequest::CurlRequest(handle_t handle, LLCurl::Multi* multi) :
+LLCurlThread::CurlRequest::CurlRequest(handle_t handle, LLCurl::Multi* multi, LLCurlThread* curl_thread) :
 	LLQueuedThread::QueuedRequest(handle, LLQueuedThread::PRIORITY_NORMAL, FLAG_AUTO_COMPLETE),
-	mMulti(multi)
+	mMulti(multi),
+	mCurlThread(curl_thread)
 {	
 }
 
@@ -807,7 +808,7 @@ LLCurlThread::CurlRequest::~CurlRequest()
 {	
 	if(mMulti)
 	{
-		delete mMulti ;
+		mCurlThread->deleteMulti(mMulti) ;
 		mMulti = NULL ;
 	}
 }
@@ -817,7 +818,7 @@ bool LLCurlThread::CurlRequest::processRequest()
 	bool completed = true ;
 	if(mMulti)
 	{
-		completed = mMulti->doPerform() ;
+		completed = mCurlThread->doMultiPerform(mMulti) ;
 		setPriority(LLQueuedThread::PRIORITY_LOW) ;
 	}
 
@@ -826,7 +827,7 @@ bool LLCurlThread::CurlRequest::processRequest()
 
 void LLCurlThread::CurlRequest::finishRequest(bool completed)
 {
-	delete mMulti ;
+	mCurlThread->deleteMulti(mMulti) ;
 	mMulti = NULL ;
 }
 	
@@ -849,7 +850,7 @@ void LLCurlThread::addMulti(LLCurl::Multi* multi)
 {
 	multi->mHandle = generateHandle() ;
 
-	CurlRequest* req = new CurlRequest(multi->mHandle, multi) ;
+	CurlRequest* req = new CurlRequest(multi->mHandle, multi, this) ;
 
 	if (!addRequest(req))
 	{
@@ -857,11 +858,22 @@ void LLCurlThread::addMulti(LLCurl::Multi* multi)
 	}
 }
 	
-void LLCurlThread::deleteMulti(LLCurl::Multi* multi)
+void LLCurlThread::killMulti(LLCurl::Multi* multi)
 {
 	multi->markDead() ;
 }
 
+//private
+bool LLCurlThread::doMultiPerform(LLCurl::Multi* multi) 
+{
+	return multi->doPerform() ;
+}
+
+//private
+void LLCurlThread::deleteMulti(LLCurl::Multi* multi) 
+{
+	delete multi ;
+}
 //------------------------------------------------------------
 
 //static
@@ -886,7 +898,7 @@ LLCurlRequest::~LLCurlRequest()
 	//stop all Multi handle background threads
 	for (curlmulti_set_t::iterator iter = mMultiSet.begin(); iter != mMultiSet.end(); ++iter)
 	{
-		LLCurl::getCurlThread()->deleteMulti(*iter) ;
+		LLCurl::getCurlThread()->killMulti(*iter) ;
 	}
 	mMultiSet.clear() ;
 }
@@ -1023,7 +1035,7 @@ S32 LLCurlRequest::process()
 		if (multi != mActiveMulti && tres == 0 && multi->mQueued == 0)
 		{
 			mMultiSet.erase(curiter);
-			LLCurl::getCurlThread()->deleteMulti(multi);
+			LLCurl::getCurlThread()->killMulti(multi);
 		}
 	}
 	mProcessing = FALSE;
@@ -1069,7 +1081,7 @@ LLCurlEasyRequest::LLCurlEasyRequest()
 
 LLCurlEasyRequest::~LLCurlEasyRequest()
 {
-	LLCurl::getCurlThread()->deleteMulti(mMulti) ;
+	LLCurl::getCurlThread()->killMulti(mMulti) ;
 }
 	
 void LLCurlEasyRequest::setopt(CURLoption option, S32 value)
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index 23a6ca67e3..a275db3e53 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -328,7 +328,7 @@ public:
 		virtual ~CurlRequest(); // use deleteRequest()
 		
 	public:
-		CurlRequest(handle_t handle, LLCurl::Multi* multi);
+		CurlRequest(handle_t handle, LLCurl::Multi* multi, LLCurlThread* curl_thread);
 
 		/*virtual*/ bool processRequest();
 		/*virtual*/ void finishRequest(bool completed);
@@ -336,8 +336,10 @@ public:
 	private:
 		// input
 		LLCurl::Multi* mMulti;
+		LLCurlThread*  mCurlThread;
 	};
-	
+	friend class CurlRequest;
+
 public:
 	LLCurlThread(bool threaded = true) ;
 	virtual ~LLCurlThread() ;
@@ -345,6 +347,10 @@ public:
 	S32 update(U32 max_time_ms);
 
 	void addMulti(LLCurl::Multi* multi) ;
+	void killMulti(LLCurl::Multi* multi) ;
+
+private:
+	bool doMultiPerform(LLCurl::Multi* multi) ;
 	void deleteMulti(LLCurl::Multi* multi) ;
 } ;
 
-- 
cgit v1.2.3


From cc2324d17de664b0dc5f4b3169b232c2c1033433 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Tue, 29 Nov 2011 16:35:54 -0800
Subject: Enabling VBO's for mac by default

---
 indra/newview/featuretable_mac.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index 1e2fbc677d..942c043081 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -51,7 +51,7 @@ RenderTerrainLODFactor			1	2.0
 RenderTransparentWater			1	1
 RenderTreeLODFactor				1	1.0
 RenderUseImpostors				1	1
-RenderVBOEnable					1	0
+RenderVBOEnable					1	1
 RenderVBOMappingDisable			1	1
 RenderVolumeLODFactor			1	2.0
 UseStartScreen					1	1
-- 
cgit v1.2.3


From 9771733ac9d2a624ac5fd4e84d60edffdcfd9ee3 Mon Sep 17 00:00:00 2001
From: Vadim ProductEngine <vsavchuk@productengine.com>
Date: Wed, 30 Nov 2011 08:18:52 +0200
Subject: EXP-1640 FIXED Fixed weirdly looking Snapshot floater in Italian and
 French locales.

---
 indra/newview/skins/default/xui/fr/floater_snapshot.xml | 2 +-
 indra/newview/skins/default/xui/it/floater_snapshot.xml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/indra/newview/skins/default/xui/fr/floater_snapshot.xml b/indra/newview/skins/default/xui/fr/floater_snapshot.xml
index 34d0957b46..365ff77ff9 100644
--- a/indra/newview/skins/default/xui/fr/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/fr/floater_snapshot.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Snapshot" title="APERÇU DE LA PHOTO" width="247">
+<floater name="Snapshot" title="APERÇU DE LA PHOTO">
 	<floater.string name="unknown">
 		inconnu
 	</floater.string>
diff --git a/indra/newview/skins/default/xui/it/floater_snapshot.xml b/indra/newview/skins/default/xui/it/floater_snapshot.xml
index 5bff19e8d7..f1c5cc4caf 100644
--- a/indra/newview/skins/default/xui/it/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/it/floater_snapshot.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Snapshot" title="ANTEPRIMA FOTOGRAFIA" width="247">
+<floater name="Snapshot" title="ANTEPRIMA FOTOGRAFIA">
 	<floater.string name="unknown">
 		sconosciuto
 	</floater.string>
-- 
cgit v1.2.3


From 19545f58ad868470ff04b452697161cd57025220 Mon Sep 17 00:00:00 2001
From: Vadim ProductEngine <vsavchuk@productengine.com>
Date: Wed, 30 Nov 2011 08:35:25 +0200
Subject: EXP-1641 FIXED Snapshot floater doesn't persist between sessions
 anymore to avoid capturing login screen.

---
 indra/newview/skins/default/xui/en/floater_snapshot.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml
index 85f65dedd3..61f2e7e72d 100644
--- a/indra/newview/skins/default/xui/en/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml
@@ -10,7 +10,7 @@
  name="Snapshot"
  help_topic="snapshot"
  save_rect="true"
- save_visibility="true"
+ save_visibility="false"
  title="SNAPSHOT PREVIEW"
  width="470">
     <floater.string
-- 
cgit v1.2.3


From ac762b0426bf5b5e0edd5d725ba6c01a39cb0248 Mon Sep 17 00:00:00 2001
From: Vadim ProductEngine <vsavchuk@productengine.com>
Date: Wed, 30 Nov 2011 19:37:12 +0200
Subject: EXP-1634 FIXED Removed the "exchange rates" link from the L$ Buy
 Dialog.

---
 indra/newview/skins/default/xui/da/floater_buy_currency.xml | 2 +-
 indra/newview/skins/default/xui/de/floater_buy_currency.xml | 2 +-
 indra/newview/skins/default/xui/en/floater_buy_currency.xml | 2 +-
 indra/newview/skins/default/xui/es/floater_buy_currency.xml | 2 +-
 indra/newview/skins/default/xui/fr/floater_buy_currency.xml | 2 +-
 indra/newview/skins/default/xui/it/floater_buy_currency.xml | 2 +-
 indra/newview/skins/default/xui/ja/floater_buy_currency.xml | 2 +-
 indra/newview/skins/default/xui/pl/floater_buy_currency.xml | 2 +-
 indra/newview/skins/default/xui/pt/floater_buy_currency.xml | 2 +-
 indra/newview/skins/default/xui/ru/floater_buy_currency.xml | 2 +-
 indra/newview/skins/default/xui/tr/floater_buy_currency.xml | 2 +-
 indra/newview/skins/default/xui/zh/floater_buy_currency.xml | 2 +-
 12 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/indra/newview/skins/default/xui/da/floater_buy_currency.xml b/indra/newview/skins/default/xui/da/floater_buy_currency.xml
index ec47b2f445..3c0428b2b0 100644
--- a/indra/newview/skins/default/xui/da/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/da/floater_buy_currency.xml
@@ -46,7 +46,7 @@
 		L$ [AMT]
 	</text>
 	<text name="currency_links">
-		[http://www.secondlife.com/my/account/payment_method_management.php payment method] | [http://www.secondlife.com/my/account/currency.php currency] | [http://www.secondlife.com/my/account/exchange_rates.php exchange rate]
+		[http://www.secondlife.com/my/account/payment_method_management.php payment method] | [http://www.secondlife.com/my/account/currency.php currency]
 	</text>
 	<text name="exchange_rate_note">
 		Indtast beløbet for at se nyeste valutakurs.
diff --git a/indra/newview/skins/default/xui/de/floater_buy_currency.xml b/indra/newview/skins/default/xui/de/floater_buy_currency.xml
index 38321b7906..e766b622f7 100644
--- a/indra/newview/skins/default/xui/de/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/de/floater_buy_currency.xml
@@ -46,7 +46,7 @@
 		[AMT] L$
 	</text>
 	<text name="currency_links">
-		[http://www.secondlife.com/my/account/payment_method_management.php?lang=de-DE Zahlungsart] | [http://www.secondlife.com/my/account/currency.php?lang=de-DE Währung] | [http://www.secondlife.com/my/account/exchange_rates.php?lang=de-DE Umtauschrate]
+		[http://www.secondlife.com/my/account/payment_method_management.php?lang=de-DE Zahlungsart] | [http://www.secondlife.com/my/account/currency.php?lang=de-DE Währung]
 	</text>
 	<text name="exchange_rate_note">
 		Geben Sie den Betrag erneut ein, um die aktuellste Umtauschrate anzuzeigen.
diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency.xml b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
index 49ca6cc8ba..6afa24d04a 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
@@ -224,7 +224,7 @@
      width="300"
      height="30"
      name="currency_links">
-      [http://www.secondlife.com/my/account/payment_method_management.php payment method] | [http://www.secondlife.com/my/account/currency.php currency] | [http://www.secondlife.com/my/account/exchange_rates.php exchange rate]
+      [http://www.secondlife.com/my/account/payment_method_management.php payment method] | [http://www.secondlife.com/my/account/currency.php currency]
     </text>
     <text
      type="string"
diff --git a/indra/newview/skins/default/xui/es/floater_buy_currency.xml b/indra/newview/skins/default/xui/es/floater_buy_currency.xml
index 43bbf0b70f..2c8848265f 100644
--- a/indra/newview/skins/default/xui/es/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/es/floater_buy_currency.xml
@@ -46,7 +46,7 @@
 		[AMT] L$
 	</text>
 	<text name="currency_links">
-		[http://www.secondlife.com/my/account/payment_method_management.php método de pago] | [http://www.secondlife.com/my/account/currency.php moneda] | [http://www.secondlife.com/my/account/exchange_rates.php tipo de cambio]
+		[http://www.secondlife.com/my/account/payment_method_management.php método de pago] | [http://www.secondlife.com/my/account/currency.php moneda]
 	</text>
 	<text name="exchange_rate_note">
 		Vuelve a escribir la cantidad para ver el tipo de cambio más reciente.
diff --git a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
index b3acc83078..d9e8e8821d 100644
--- a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
@@ -47,7 +47,7 @@ le Lindex...
 		[AMT] L$
 	</text>
 	<text name="currency_links">
-		[http://www.secondlife.com/my/account/payment_method_management.php?lang=fr-FR mode de paiement] | [http://www.secondlife.com/my/account/currency.php?lang=fr-FR devise] | [http://www.secondlife.com/my/account/exchange_rates.php?lang=fr-FR taux de change]
+		[http://www.secondlife.com/my/account/payment_method_management.php?lang=fr-FR mode de paiement] | [http://www.secondlife.com/my/account/currency.php?lang=fr-FR devise]
 	</text>
 	<text name="exchange_rate_note">
 		Saisissez à nouveau le montant pour voir le taux de change actuel.
diff --git a/indra/newview/skins/default/xui/it/floater_buy_currency.xml b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
index 635b56d37a..d985ad2b3c 100644
--- a/indra/newview/skins/default/xui/it/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
@@ -46,7 +46,7 @@
 		[AMT]L$
 	</text>
 	<text name="currency_links">
-		[http://www.secondlife.com/my/account/payment_method_management.php payment method] | [http://www.secondlife.com/my/account/currency.php currency] | [http://www.secondlife.com/my/account/exchange_rates.php exchange rate]
+		[http://www.secondlife.com/my/account/payment_method_management.php payment method] | [http://www.secondlife.com/my/account/currency.php currency]
 	</text>
 	<text name="exchange_rate_note">
 		Riscrivi l&apos;importo per vedere l&apos;ultimo tasso al cambio.
diff --git a/indra/newview/skins/default/xui/ja/floater_buy_currency.xml b/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
index 22af6e0ea2..e447eefe0e 100644
--- a/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
@@ -46,7 +46,7 @@
 		L$ [AMT]
 	</text>
 	<text name="currency_links">
-		[http://www.secondlife.com/my/account/payment_method_management.php?lang=ja-JP 支払方法] | [http://www.secondlife.com/my/account/currency.php?lang=ja-JP 通貨] | [http://www.secondlife.com/my/account/exchange_rates.php?lang=ja-JP 換算レート]
+		[http://www.secondlife.com/my/account/payment_method_management.php?lang=ja-JP 支払方法] | [http://www.secondlife.com/my/account/currency.php?lang=ja-JP 通貨]
 	</text>
 	<text name="exchange_rate_note">
 		金額を再入力して最新換算レートを確認します。
diff --git a/indra/newview/skins/default/xui/pl/floater_buy_currency.xml b/indra/newview/skins/default/xui/pl/floater_buy_currency.xml
index f2a6579dc3..3e51761b37 100644
--- a/indra/newview/skins/default/xui/pl/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/pl/floater_buy_currency.xml
@@ -46,7 +46,7 @@
 		[AMT]L$
 	</text>
 	<text name="currency_links">
-		[http://www.secondlife.com/my/account/payment_method_management.php metoda płatności] | [http://www.secondlife.com/my/account/currency.php waluta] | [http://www.secondlife.com/my/account/exchange_rates.php kurs wymiany]
+		[http://www.secondlife.com/my/account/payment_method_management.php metoda płatności] | [http://www.secondlife.com/my/account/currency.php waluta]
 	</text>
 	<text name="exchange_rate_note">
 		Wpisz ponownie kwotę aby zobaczyć ostatni kurs wymiany.
diff --git a/indra/newview/skins/default/xui/pt/floater_buy_currency.xml b/indra/newview/skins/default/xui/pt/floater_buy_currency.xml
index a737212b50..b5ba477fe5 100644
--- a/indra/newview/skins/default/xui/pt/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/pt/floater_buy_currency.xml
@@ -46,7 +46,7 @@
 		L$ [AMT]
 	</text>
 	<text name="currency_links">
-		[http://www.secondlife.com/my/account/payment_method_management.php payment method] | [http://www.secondlife.com/my/account/currency.php currency] | [http://www.secondlife.com/my/account/exchange_rates.php exchange rate]
+		[http://www.secondlife.com/my/account/payment_method_management.php payment method] | [http://www.secondlife.com/my/account/currency.php currency]
 	</text>
 	<text name="exchange_rate_note">
 		Digite o valor novamente para ver o câmbio atual.
diff --git a/indra/newview/skins/default/xui/ru/floater_buy_currency.xml b/indra/newview/skins/default/xui/ru/floater_buy_currency.xml
index 7690ff2a6c..7d34ca3274 100644
--- a/indra/newview/skins/default/xui/ru/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/ru/floater_buy_currency.xml
@@ -46,7 +46,7 @@
 		L$ [AMT]
 	</text>
 	<text name="currency_links">
-		[http://www.secondlife.com/my/account/payment_method_management.php способ оплаты] | [http://www.secondlife.com/my/account/currency.php валюта] | [http://www.secondlife.com/my/account/exchange_rates.php обменный курс]
+		[http://www.secondlife.com/my/account/payment_method_management.php способ оплаты] | [http://www.secondlife.com/my/account/currency.php валюта]
 	</text>
 	<text name="exchange_rate_note">
 		Повторно введите сумму, чтобы увидеть новый обменный курс.
diff --git a/indra/newview/skins/default/xui/tr/floater_buy_currency.xml b/indra/newview/skins/default/xui/tr/floater_buy_currency.xml
index 48cd93ccf9..6608fd72e1 100644
--- a/indra/newview/skins/default/xui/tr/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/tr/floater_buy_currency.xml
@@ -46,7 +46,7 @@
 		L$ [AMT]
 	</text>
 	<text name="currency_links">
-		[http://www.secondlife.com/my/account/payment_method_management.php ödeme yöntemi] | [http://www.secondlife.com/my/account/currency.php para birimi | [http://www.secondlife.com/my/account/exchange_rates.php döviz kurları]
+		[http://www.secondlife.com/my/account/payment_method_management.php ödeme yöntemi] | [http://www.secondlife.com/my/account/currency.php para birimi
 	</text>
 	<text name="exchange_rate_note">
 		En son döviz kurunu görmek için miktarı yeniden girin.
diff --git a/indra/newview/skins/default/xui/zh/floater_buy_currency.xml b/indra/newview/skins/default/xui/zh/floater_buy_currency.xml
index d63e73c6f1..9f6591faf9 100644
--- a/indra/newview/skins/default/xui/zh/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/zh/floater_buy_currency.xml
@@ -46,7 +46,7 @@
 		L$ [AMT]
 	</text>
 	<text name="currency_links">
-		[http://www.secondlife.com/my/account/payment_method_management.php payment method] | [http://www.secondlife.com/my/account/currency.php currency] | [http://www.secondlife.com/my/account/exchange_rates.php exchange rate]
+		[http://www.secondlife.com/my/account/payment_method_management.php payment method] | [http://www.secondlife.com/my/account/currency.php currency]
 	</text>
 	<text name="exchange_rate_note">
 		Re-enter amount to see the latest exchange rate.
-- 
cgit v1.2.3


From 83c3d378275e4da6f4aa0b148853abf770f73e86 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Wed, 30 Nov 2011 11:20:26 -0700
Subject: trivial: change a log info for memory failure for LLImageBase

---
 indra/llimage/llimage.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index c239e3df88..56e01ac851 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -195,7 +195,7 @@ U8* LLImageBase::allocateData(S32 size)
 		mData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size);
 		if (!mData)
 		{
-			llwarns << "allocate image data: " << size << llendl;
+			llwarns << "Failed to allocate image data size [" << size << "]" << llendl;
 			size = 0 ;
 			mWidth = mHeight = 0 ;
 			mBadBufferAllocation = true ;
-- 
cgit v1.2.3


From e6f5a57395a64b8dcfe85f20b0a63402c77a3c5f Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Wed, 30 Nov 2011 11:21:22 -0700
Subject: fix for SH-2668: "ocean" water is always 20m high instead of the
 Region Water Height

---
 indra/newview/llworld.cpp | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 6f6e0d2334..676287c0ad 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -818,14 +818,11 @@ void LLWorld::updateWaterObjects()
 	max_x = (S32)region_x + range;
 	max_y = (S32)region_y + range;
 
-	F32 height = 0.f;
-	
 	for (region_list_t::iterator iter = mRegionList.begin();
 		 iter != mRegionList.end(); ++iter)
 	{
 		LLViewerRegion* regionp = *iter;
 		LLVOWater* waterp = regionp->getLand().getWaterObj();
-		height += regionp->getWaterHeight();
 		if (waterp)
 		{
 			gObjectList.updateActive(waterp);
@@ -842,6 +839,7 @@ void LLWorld::updateWaterObjects()
 
 	// Now, get a list of the holes
 	S32 x, y;
+	F32 water_height = gAgent.getRegion()->getWaterHeight() + 256.f;
 	for (x = min_x; x <= max_x; x += rwidth)
 	{
 		for (y = min_y; y <= max_y; y += rwidth)
@@ -853,7 +851,7 @@ void LLWorld::updateWaterObjects()
 				waterp->setUseTexture(FALSE);
 				waterp->setPositionGlobal(LLVector3d(x + rwidth/2,
 													 y + rwidth/2,
-													 256.f+DEFAULT_WATER_HEIGHT));
+													 water_height));
 				waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, 512.f));
 				gPipeline.createObject(waterp);
 				mHoleWaterObjects.push_back(waterp);
@@ -910,8 +908,7 @@ void LLWorld::updateWaterObjects()
 		}
 
 		waterp->setRegion(gAgent.getRegion());
-		LLVector3d water_pos(water_center_x, water_center_y, 
-			DEFAULT_WATER_HEIGHT+256.f);
+		LLVector3d water_pos(water_center_x, water_center_y, water_height) ;
 		LLVector3 water_scale((F32) dim[0], (F32) dim[1], 512.f);
 
 		//stretch out to horizon
-- 
cgit v1.2.3


From 8294179dbc7e2376fa7773a77e536e9a31479b87 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Wed, 30 Nov 2011 15:26:09 -0500
Subject: Added tag 3.2.4-start for changeset 3fe994349fae

---
 .hgtags | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.hgtags b/.hgtags
index b863bbe37b..168ff66cf9 100644
--- a/.hgtags
+++ b/.hgtags
@@ -228,3 +228,4 @@ c4911ec8cd81e676dfd2af438b3e065407a94a7a 3.2.1-start
 80f3e30d8aa4d8f674a48bd742aaa6d8e9eae0b5 3.2.3-start
 a8c7030d6845186fac7c188be4323a0e887b4184 DRTVWR-99_3.2.1-release
 a8c7030d6845186fac7c188be4323a0e887b4184 3.2.1-release
+3fe994349fae64fc40874bb59db387131eb35a41 3.2.4-start
-- 
cgit v1.2.3


From f5a94e0f8196c5c068995090cd57bb27e97aaac9 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Wed, 30 Nov 2011 15:27:00 -0500
Subject: increment viewer version to 3.2.5

---
 indra/llcommon/llversionviewer.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index b50405421d..deac3d1780 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -29,7 +29,7 @@
 
 const S32 LL_VERSION_MAJOR = 3;
 const S32 LL_VERSION_MINOR = 2;
-const S32 LL_VERSION_PATCH = 4;
+const S32 LL_VERSION_PATCH = 5;
 const S32 LL_VERSION_BUILD = 0;
 
 const char * const LL_CHANNEL = "Second Life Developer";
-- 
cgit v1.2.3


From 8aa0ef2636b15e0e8a4e15df3169a17b2d15e8d2 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Thu, 1 Dec 2011 12:06:47 -0700
Subject: fix for SH-2560: Nearby avatar textures fail to load and SH-2671:
 sometimes other avatar textures don't load

---
 indra/newview/llviewertexture.cpp | 29 +++++++++++++++++------------
 1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 786e2b73b1..b0f5361a79 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -2269,6 +2269,7 @@ void LLViewerFetchedTexture::unpauseLoadedCallbacks(const LLLoadedCallbackEntry:
 		}
 	}
 	mPauseLoadedCallBacks = FALSE ;
+	mLastCallBackActiveTime = sCurrentTime ;
 	if(need_raw)
 	{
 		mSaveRawImage = TRUE ;
@@ -2310,6 +2311,11 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
 {
 	static const F32 MAX_INACTIVE_TIME = 120.f ; //seconds
 
+	if(mPauseLoadedCallBacks)
+	{
+		destroyRawImage();
+		return false; //paused
+	}
 	if (mNeedsCreateTexture)
 	{
 		return false;
@@ -2337,12 +2343,7 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
 
 		// Remove ourself from the global list of textures with callbacks
 		gTextureList.mCallbackList.erase(this);
-	}
-	if(mPauseLoadedCallBacks)
-	{
-		destroyRawImage();
-		return res; //paused
-	}
+	}	
 
 	S32 gl_discard = getDiscardLevel();
 
@@ -2604,7 +2605,11 @@ bool LLViewerFetchedTexture::needsToSaveRawImage()
 
 void LLViewerFetchedTexture::destroyRawImage()
 {	
-	if (mAuxRawImage.notNull()) sAuxCount--;
+	if (mAuxRawImage.notNull())
+	{
+		sAuxCount--;
+		mAuxRawImage = NULL;
+	}
 
 	if (mRawImage.notNull()) 
 	{
@@ -2618,12 +2623,12 @@ void LLViewerFetchedTexture::destroyRawImage()
 			}		
 			setCachedRawImage() ;
 		}
+		
+		mRawImage = NULL;
+	
+		mIsRawImageValid = FALSE;
+		mRawDiscardLevel = INVALID_DISCARD_LEVEL;
 	}
-
-	mRawImage = NULL;
-	mAuxRawImage = NULL;
-	mIsRawImageValid = FALSE;
-	mRawDiscardLevel = INVALID_DISCARD_LEVEL;
 }
 
 //use the mCachedRawImage to (re)generate the gl texture.
-- 
cgit v1.2.3


From c9c03ffa0ca21eeb2786920cf9c0cb547be8a468 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Thu, 1 Dec 2011 14:52:37 -0700
Subject: fix for sh-2735: LLCurl causes SL to freeze when logout

---
 indra/newview/llappviewer.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 9d40a8a60e..e80475f096 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1781,6 +1781,7 @@ bool LLAppViewer::cleanup()
 		pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
 		pending += LLVFSThread::updateClass(0);
 		pending += LLLFSThread::updateClass(0);
+		pending += LLCurl::getCurlThread()->update(1) ;
 		F64 idle_time = idleTimer.getElapsedTimeF64();
 		if(!pending)
 		{
@@ -1792,6 +1793,7 @@ bool LLAppViewer::cleanup()
 			break;
 		}
 	}
+	LLCurl::getCurlThread()->pause() ;
 
 	// Delete workers first
 	// shotdown all worker threads before deleting them in case of co-dependencies
-- 
cgit v1.2.3


From b5346c6b64ce955ed71ddc6f64bc7a864111a8e4 Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Thu, 1 Dec 2011 15:46:39 -0800
Subject: SH-2726 FIX -- Texture Console and Debug Console inaccessable

* Removed debug view post build step and moved initialization to first draw for proper setup.
---
 indra/newview/lldebugview.cpp | 12 +++++-------
 indra/newview/lldebugview.h   |  2 --
 2 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/indra/newview/lldebugview.cpp b/indra/newview/lldebugview.cpp
index 92ac336d0d..7d3170cb76 100644
--- a/indra/newview/lldebugview.cpp
+++ b/indra/newview/lldebugview.cpp
@@ -72,13 +72,6 @@ LLDebugView::~LLDebugView()
 	gTextureCategoryView = NULL;
 }
 
-BOOL LLDebugView::postBuild()
-{
-	mFloaterSnapRegion = getRootView()->getChildView("floater_snap_region");
-	
-	return TRUE;
-}
-
 void LLDebugView::init()
 {
 	LLRect r;
@@ -157,6 +150,11 @@ void LLDebugView::init()
 
 void LLDebugView::draw()
 {
+	if (mFloaterSnapRegion == NULL)
+	{
+		mFloaterSnapRegion = getRootView()->getChildView("floater_snap_region");
+	}
+
 	LLRect debug_rect;
 	mFloaterSnapRegion->localRectToOtherView(mFloaterSnapRegion->getLocalRect(), &debug_rect, getParent());
 
diff --git a/indra/newview/lldebugview.h b/indra/newview/lldebugview.h
index 33d6a7394f..5aec77ad62 100644
--- a/indra/newview/lldebugview.h
+++ b/indra/newview/lldebugview.h
@@ -55,8 +55,6 @@ public:
 	LLDebugView(const Params&);
 	~LLDebugView();
 
-	BOOL postBuild();
-	
 	void init();
 	void draw();
 	
-- 
cgit v1.2.3


From bf24ffd27a6c5ceb94990442c62dc51565330cb8 Mon Sep 17 00:00:00 2001
From: Simon Linden <simon@lindenlab.com>
Date: Thu, 1 Dec 2011 16:37:51 -0800
Subject: ER-1473:  fix teleporting in sit mode.  Viewer fix - reviewed by
 Callum

---
 indra/newview/llviewermessage.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index dca5cdd06d..ad333a71ff 100755
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -3638,6 +3638,9 @@ void process_teleport_finish(LLMessageSystem* msg, void**)
 	gCacheName->setUpstream(sim);
 */
 
+	// Make sure we're standing
+	gAgent.standUp();
+
 	// now, use the circuit info to tell simulator about us!
 	LL_INFOS("Messaging") << "process_teleport_finish() Enabling "
 			<< sim_host << " with code " << msg->mOurCircuitCode << LL_ENDL;
-- 
cgit v1.2.3