From 3c05ebd28635e867f9726062b08cdbf4a7b53b22 Mon Sep 17 00:00:00 2001
From: Monty Brandenberg <monty@lindenlab.com>
Date: Thu, 16 Dec 2010 16:42:26 -0800
Subject: [PATCH] ESC-237 No static init of LLAtomics and move TFRequest out of
 unnamed namespace. Linux startup crash appears to be due to static/global C++
 init of LLAtomic types.  The initializer with explicit value makes some
 runtime calls and it looks like these assume, at least on Linux, that
 apr_initialize() has been called.  So move the static POST count to a member
 and provide accessors and increment/decrement.  Command queue was built on a
 pointer to a class in anonymous namespace and that's not quite valid.  Made
 it a nested class (really a nested forward declaration) while keeping the
 derived classes in anonymous.

---
 indra/newview/lltexturefetch.cpp | 42 +++++++++++++++-----------------
 indra/newview/lltexturefetch.h   | 16 ++++++++++--
 2 files changed, 33 insertions(+), 25 deletions(-)

diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 25ad2fe7177..4f63abb152d 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -388,9 +388,6 @@ class HTTPGetResponder : public LLCurl::Responder
 
 // Cross-thread messaging for asset metrics.
 
-namespace
-{
-
 /**
  * @brief Base class for cross-thread requests made of the fetcher
  *
@@ -490,7 +487,7 @@ namespace
  *       (i.e. deep copy) when necessary.
  *
  */
-class TFRequest // : public LLQueuedThread::QueuedRequest
+class LLTextureFetch::TFRequest // : public LLQueuedThread::QueuedRequest
 {
 public:
 	// Default ctors and assignment operator are correct.
@@ -505,6 +502,8 @@ class TFRequest // : public LLQueuedThread::QueuedRequest
 	virtual bool doWork(LLTextureFetch * fetcher) = 0;
 };
 
+namespace 
+{
 
 /**
  * @brief Implements a 'Set Region' cross-thread command.
@@ -517,11 +516,11 @@ class TFRequest // : public LLQueuedThread::QueuedRequest
  *
  * Corresponds to LLTextureFetch::commandSetRegion()
  */
-class TFReqSetRegion : public TFRequest
+class TFReqSetRegion : public LLTextureFetch::TFRequest
 {
 public:
 	TFReqSetRegion(U64 region_handle)
-		: TFRequest(),
+		: LLTextureFetch::TFRequest(),
 		  mRegionHandle(region_handle)
 		{}
 	TFReqSetRegion & operator=(const TFReqSetRegion &);	// Not defined
@@ -550,7 +549,7 @@ class TFReqSetRegion : public TFRequest
  *
  * Corresponds to LLTextureFetch::commandSendMetrics()
  */
-class TFReqSendMetrics : public TFRequest
+class TFReqSendMetrics : public LLTextureFetch::TFRequest
 {
 public:
     /**
@@ -574,7 +573,7 @@ class TFReqSendMetrics : public TFRequest
 					 const LLUUID & session_id,
 					 const LLUUID & agent_id,
 					 LLViewerAssetStats * main_stats)
-		: TFRequest(),
+		: LLTextureFetch::TFRequest(),
 		  mCapsURL(caps_url),
 		  mSessionID(session_id),
 		  mAgentID(agent_id),
@@ -593,14 +592,6 @@ class TFReqSendMetrics : public TFRequest
 	LLViewerAssetStats * mMainStats;
 };
 
-/*
- * Count of POST requests outstanding.  We maintain the count
- * indirectly in the CURL request responder's ctor and dtor and
- * use it when determining whether or not to sleep the thread.  Can't
- * use the LLCurl module's request counter as it isn't thread compatible.
- */
-LLAtomic32<S32> curl_post_request_count = 0;
-
 /*
  * Examines the merged viewer metrics report and if found to be too long,
  * will attempt to truncate it in some reasonable fashion.
@@ -1834,6 +1825,7 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
 	  mCurlGetRequest(NULL),
 	  mQAMode(qa_mode)
 {
+	mCurlPOSTRequestCount = 0;
 	mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS");
 	mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), gSavedSettings.getU32("TextureLoggingThreshold"));
 }
@@ -2149,7 +2141,7 @@ S32 LLTextureFetch::getPending()
         LLMutexLock lock(&mQueueMutex);
         
         res = mRequestQueue.size();
-        res += curl_post_request_count;
+        res += mCurlPOSTRequestCount;
         res += mCommands.size();
     }
 	unlockData();
@@ -2175,7 +2167,7 @@ bool LLTextureFetch::runCondition()
 		have_no_commands = mCommands.empty();
 	}
 	
-    bool have_no_curl_requests(0 == curl_post_request_count);
+    bool have_no_curl_requests(0 == mCurlPOSTRequestCount);
 	
 	return ! (have_no_commands
 			  && have_no_curl_requests
@@ -2769,7 +2761,7 @@ void LLTextureFetch::cmdEnqueue(TFRequest * req)
 	unpause();
 }
 
-TFRequest * LLTextureFetch::cmdDequeue()
+LLTextureFetch::TFRequest * LLTextureFetch::cmdDequeue()
 {
 	TFRequest * ret = 0;
 	
@@ -2856,22 +2848,24 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
 	class lcl_responder : public LLCurl::Responder
 	{
 	public:
-		lcl_responder(S32 expected_sequence,
+		lcl_responder(LLTextureFetch * fetcher,
+					  S32 expected_sequence,
                       volatile const S32 & live_sequence,
                       volatile bool & reporting_break,
 					  volatile bool & reporting_started)
 			: LLCurl::Responder(),
+			  mFetcher(fetcher),
               mExpectedSequence(expected_sequence),
               mLiveSequence(live_sequence),
 			  mReportingBreak(reporting_break),
 			  mReportingStarted(reporting_started)
 			{
-                curl_post_request_count++;
+                mFetcher->incrCurlPOSTCount();
             }
         
         ~lcl_responder()
             {
-                curl_post_request_count--;
+                mFetcher->decrCurlPOSTCount();
             }
 
 		// virtual
@@ -2896,6 +2890,7 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
 			}
 
 	private:
+		LLTextureFetch * mFetcher;
         S32 mExpectedSequence;
         volatile const S32 & mLiveSequence;
 		volatile bool & mReportingBreak;
@@ -2939,7 +2934,8 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
 		fetcher->getCurlRequest().post(mCapsURL,
 									   headers,
 									   merged_llsd,
-									   new lcl_responder(report_sequence,
+									   new lcl_responder(fetcher,
+														 report_sequence,
                                                          report_sequence,
                                                          LLTextureFetch::svMetricsDataBreak,
 														 reporting_started));
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index a8fd3ce244a..ad00a7ea36f 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -33,6 +33,7 @@
 #include "llworkerthread.h"
 #include "llcurl.h"
 #include "lltextureinfo.h"
+#include "llapr.h"
 
 class LLViewerTexture;
 class LLTextureFetchWorker;
@@ -42,8 +43,6 @@ class LLImageDecodeThread;
 class LLHost;
 class LLViewerAssetStats;
 
-namespace { class TFRequest; }
-
 // Interface class
 class LLTextureFetch : public LLWorkerThread
 {
@@ -54,6 +53,8 @@ class LLTextureFetch : public LLWorkerThread
 	LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* imagedecodethread, bool threaded, bool qa_mode);
 	~LLTextureFetch();
 
+	class TFRequest;
+	
 	/*virtual*/ S32 update(U32 max_time_ms);	
 	void shutDownTextureCacheThread() ; //called in the main thread after the TextureCacheThread shuts down.
 	void shutDownImageDecodeThread() ;  //called in the main thread after the ImageDecodeThread shuts down.
@@ -100,6 +101,10 @@ class LLTextureFetch : public LLWorkerThread
 
 	bool isQAMode() const				{ return mQAMode; }
 
+	// Curl POST counter maintenance
+	inline void incrCurlPOSTCount()		{ mCurlPOSTRequestCount++; }
+	inline void decrCurlPOSTCount()		{ mCurlPOSTRequestCount--; }
+
 protected:
 	void addToNetworkQueue(LLTextureFetchWorker* worker);
 	void removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel);
@@ -187,6 +192,13 @@ class LLTextureFetch : public LLWorkerThread
 
 	// If true, modifies some behaviors that help with QA tasks.
 	const bool mQAMode;
+
+	// Count of POST requests outstanding.  We maintain the count
+	// indirectly in the CURL request responder's ctor and dtor and
+	// use it when determining whether or not to sleep the thread.  Can't
+	// use the LLCurl module's request counter as it isn't thread compatible.
+	// *NOTE:  Don't mix Atomic and static, apr_initialize must be called first.
+	LLAtomic32<S32> mCurlPOSTRequestCount;
 	
 public:
 	// A probabilistically-correct indicator that the current
-- 
GitLab