From fbd5bd7adc205acecc49c7e9887efa3bca6552d0 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Mon, 1 Aug 2011 17:50:43 -0500
Subject: [PATCH] SH-2183 Add a debug setting to control whether or not to use
 multiple threads in LLCurl

---
 indra/llcrashlogger/llcrashlogger.cpp   |   2 +-
 indra/llmessage/llcurl.cpp              | 101 +++++++++++++++++-------
 indra/llmessage/llcurl.h                |   4 +-
 indra/newview/app_settings/settings.xml |  11 +++
 indra/newview/llappviewer.cpp           |   2 +-
 5 files changed, 87 insertions(+), 33 deletions(-)

diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp
index 93f3c910bd7..331a1692ee8 100644
--- a/indra/llcrashlogger/llcrashlogger.cpp
+++ b/indra/llcrashlogger/llcrashlogger.cpp
@@ -380,7 +380,7 @@ void LLCrashLogger::updateApplication(const std::string& message)
 
 bool LLCrashLogger::init()
 {
-	LLCurl::initClass();
+	LLCurl::initClass(false);
 
 	// We assume that all the logs we're looking for reside on the current drive
 	gDirUtilp->initAppDirs("SecondLife");
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index b7208f3e193..ece539bb48e 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -26,6 +26,7 @@
  * $/LicenseInfo$
  */
 
+
 #if LL_WINDOWS
 #define SAFE_SSL 1
 #elif LL_DARWIN
@@ -84,6 +85,8 @@ S32 gCurlMultiCount = 0;
 std::vector<LLMutex*> LLCurl::sSSLMutex;
 std::string LLCurl::sCAPath;
 std::string LLCurl::sCAFile;
+bool LLCurl::sMultiThreaded = false;
+
 
 void check_curl_code(CURLcode code)
 {
@@ -601,6 +604,7 @@ class LLCurl::Multi : public LLThread
 
 	S32 process();
 	void perform();
+	void doPerform();
 	
 	virtual void run();
 
@@ -634,7 +638,14 @@ LLCurl::Multi::Multi()
 	  mPerformState(PERFORM_STATE_READY)
 {
 	mQuitting = false;
-	mSignal = new LLCondition(NULL);
+	if (LLCurl::sMultiThreaded)
+	{
+		mSignal = new LLCondition(NULL);
+	}
+	else
+	{
+		mSignal = NULL;
+	}
 
 	mCurlMultiHandle = curl_multi_init();
 	if (!mCurlMultiHandle)
@@ -681,37 +692,51 @@ CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue)
 
 void LLCurl::Multi::perform()
 {
-	if (mPerformState == PERFORM_STATE_READY)
+	if (LLCurl::sMultiThreaded)
+	{
+		if (mPerformState == PERFORM_STATE_READY)
+		{
+			mSignal->signal();
+		}
+	}
+	else
 	{
-		mSignal->signal();
+		doPerform();
 	}
 }
 
 void LLCurl::Multi::run()
 {
+	llassert(LLCurl::sMultiThreaded);
+
 	while (!mQuitting)
 	{
 		mSignal->wait();
 		mPerformState = PERFORM_STATE_PERFORMING;
 		if (!mQuitting)
 		{
-			S32 q = 0;
-			for (S32 call_count = 0;
-				 call_count < MULTI_PERFORM_CALL_REPEAT;
-				 call_count += 1)
-			{
-				CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q);
-				if (CURLM_CALL_MULTI_PERFORM != code || q == 0)
-				{
-					check_curl_multi_code(code);
-					break;
-				}
-	
-			}
-			mQueued = q;
-			mPerformState = PERFORM_STATE_COMPLETED;
+			doPerform();
+		}
+	}
+}
+
+void LLCurl::Multi::doPerform()
+{
+	S32 q = 0;
+	for (S32 call_count = 0;
+			call_count < MULTI_PERFORM_CALL_REPEAT;
+			call_count += 1)
+	{
+		CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q);
+		if (CURLM_CALL_MULTI_PERFORM != code || q == 0)
+		{
+			check_curl_multi_code(code);
+			break;
 		}
+	
 	}
+	mQueued = q;
+	mPerformState = PERFORM_STATE_COMPLETED;
 }
 
 S32 LLCurl::Multi::process()
@@ -839,10 +864,13 @@ LLCurlRequest::~LLCurlRequest()
 	{
 		LLCurl::Multi* multi = *iter;
 		multi->mQuitting = true;
-		while (!multi->isStopped())
+		if (LLCurl::sMultiThreaded)
 		{
-			multi->mSignal->signal();
-			apr_sleep(1000);
+			while (!multi->isStopped())
+			{
+				multi->mSignal->signal();
+				apr_sleep(1000);
+			}
 		}
 	}
 	for_each(mMultiSet.begin(), mMultiSet.end(), DeletePointer());
@@ -852,7 +880,10 @@ void LLCurlRequest::addMulti()
 {
 	llassert_always(mThreadID == LLThread::currentID());
 	LLCurl::Multi* multi = new LLCurl::Multi();
-	multi->start();
+	if (LLCurl::sMultiThreaded)
+	{
+		multi->start();
+	}
 	mMultiSet.insert(multi);
 	mActiveMulti = multi;
 	mActiveRequestCount = 0;
@@ -983,10 +1014,13 @@ S32 LLCurlRequest::process()
 		{
 			mMultiSet.erase(curiter);
 			multi->mQuitting = true;
-			while (!multi->isStopped())
+			if (LLCurl::sMultiThreaded)
 			{
-				multi->mSignal->signal();
-				apr_sleep(1000);
+				while (!multi->isStopped())
+				{
+					multi->mSignal->signal();
+					apr_sleep(1000);
+				}
 			}
 
 			delete multi;
@@ -1023,7 +1057,10 @@ LLCurlEasyRequest::LLCurlEasyRequest()
 	  mResultReturned(false)
 {
 	mMulti = new LLCurl::Multi();
-	mMulti->start();
+	if (LLCurl::sMultiThreaded)
+	{
+		mMulti->start();
+	}
 	mEasy = mMulti->allocEasy();
 	if (mEasy)
 	{
@@ -1035,10 +1072,13 @@ LLCurlEasyRequest::LLCurlEasyRequest()
 LLCurlEasyRequest::~LLCurlEasyRequest()
 {
 	mMulti->mQuitting = true;
-	while (!mMulti->isStopped())
+	if (LLCurl::sMultiThreaded)
 	{
-		mMulti->mSignal->signal();
-		apr_sleep(1000);
+		while (!mMulti->isStopped())
+		{
+			mMulti->mSignal->signal();
+			apr_sleep(1000);
+		}
 	}
 	delete mMulti;
 }
@@ -1234,8 +1274,9 @@ unsigned long LLCurl::ssl_thread_id(void)
 }
 #endif
 
-void LLCurl::initClass()
+void LLCurl::initClass(bool multi_threaded)
 {
+	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
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index 56d086c30a8..b2c7b36a76f 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -55,6 +55,8 @@ class LLCurl
 	class Easy;
 	class Multi;
 
+	static bool sMultiThreaded;
+
 	struct TransferInfo
 	{
 		TransferInfo() : mSizeDownload(0.0), mTotalTime(0.0), mSpeedDownload(0.0) {}
@@ -159,7 +161,7 @@ class LLCurl
 	/**
 	 * @ brief Initialize LLCurl class
 	 */
-	static void initClass();
+	static void initClass(bool multi_threaded = false);
 
 	/**
 	 * @ brief Cleanup LLCurl class
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 7330c76b01c..2b38a8028c0 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -1803,6 +1803,17 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+  <key>CurlUseMultipleThreads</key>
+  <map>
+    <key>Comment</key>
+    <string>Use background threads for executing curl_multi_perform (requires restart)</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Boolean</string>
+    <key>Value</key>
+    <integer>1</integer>
+  </map>
     <key>Cursor3D</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index b65933f8a1d..d12b971bde9 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -708,7 +708,7 @@ bool LLAppViewer::init()
 
     // *NOTE:Mani - LLCurl::initClass is not thread safe. 
     // Called before threads are created.
-    LLCurl::initClass();
+    LLCurl::initClass(gSavedSettings.getBOOL("CurlUseMultipleThreads"));
 	LL_INFOS("InitInfo") << "LLCurl initialized." << LL_ENDL ;
 
     LLMachineID::init();
-- 
GitLab