From b4766d2fde6b74c5a4a50cdde4373b5261a020e2 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao 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 ++++++++++++++++++++++++++++----------------- 1 file changed, 220 insertions(+), 136 deletions(-) (limited to 'indra/llmessage/llcurl.cpp') 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 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 LLCurl::Easy::sFreeHandles; std::set 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; iupdate(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::iterator iter = Easy::sFreeHandles.begin(); iter != Easy::sFreeHandles.end(); ++iter) { CURL* curl = *iter; -- cgit v1.2.3 From 3fc4c14464c1b8152108a5332b754d5b2671e54d Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Tue, 29 Nov 2011 16:18:50 -0700 Subject: fix a mac build error: a friend declaration issue. --- indra/llmessage/llcurl.cpp | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'indra/llmessage/llcurl.cpp') 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) -- cgit v1.2.3 From 09feaac844d67a94ffe8c98a201e1e7f2f84be9a Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Mon, 5 Dec 2011 13:23:05 -0700 Subject: fix for sh-2738: Texture fetching freezes due to LLcurl --- indra/llmessage/llcurl.cpp | 54 +++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 29 deletions(-) (limited to 'indra/llmessage/llcurl.cpp') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 7ca25d07fc..228f039132 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -585,37 +585,30 @@ void LLCurl::Multi::unlock() void LLCurl::Multi::markDead() { - if(mDeletionMutexp) - { - mDeletionMutexp->lock() ; - } - + LLMutexLock lock(mDeletionMutexp) ; + mDead = TRUE ; - - if(mDeletionMutexp) - { - mDeletionMutexp->unlock() ; - } } void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state) { - lock() ; + LLMutexLock lock(mMutexp) ; + mState = state ; if(mState == STATE_READY) { LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_NORMAL) ; } - unlock() ; } LLCurl::Multi::ePerformState LLCurl::Multi::getState() { ePerformState state ; - lock() ; - state = mState ; - unlock() ; + { + LLMutexLock lock(mMutexp) ; + state = mState ; + } return state ; } @@ -635,13 +628,15 @@ bool LLCurl::Multi::waitToComplete() bool completed ; - lock() ; - completed = (STATE_COMPLETED == mState) ; - if(!completed) { - LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ; + LLMutexLock lock(mMutexp) ; + + completed = (STATE_COMPLETED == mState) ; + if(!completed) + { + LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ; + } } - unlock() ; return completed; } @@ -655,10 +650,8 @@ CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue) //return true if dead bool LLCurl::Multi::doPerform() { - if(mDeletionMutexp) - { - mDeletionMutexp->lock() ; - } + LLMutexLock lock(mDeletionMutexp) ; + bool dead = mDead ; if(mDead) @@ -675,6 +668,8 @@ bool LLCurl::Multi::doPerform() call_count < MULTI_PERFORM_CALL_REPEAT; call_count++) { + LLMutexLock lock(mMutexp) ; + CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q); if (CURLM_CALL_MULTI_PERFORM != code || q == 0) { @@ -688,11 +683,6 @@ bool LLCurl::Multi::doPerform() setState(STATE_COMPLETED) ; } - if(mDeletionMutexp) - { - mDeletionMutexp->unlock() ; - } - return dead ; } @@ -764,6 +754,8 @@ LLCurl::Easy* LLCurl::Multi::allocEasy() bool LLCurl::Multi::addEasy(Easy* easy) { + LLMutexLock lock(mMutexp) ; + CURLMcode mcode = curl_multi_add_handle(mCurlMultiHandle, easy->getCurlHandle()); check_curl_multi_code(mcode); //if (mcode != CURLM_OK) @@ -776,6 +768,8 @@ bool LLCurl::Multi::addEasy(Easy* easy) void LLCurl::Multi::easyFree(Easy* easy) { + LLMutexLock lock(mMutexp) ; + mEasyActiveList.erase(easy); mEasyActiveMap.erase(easy->getCurlHandle()); if (mEasyFreeList.size() < EASY_HANDLE_POOL_SIZE) @@ -791,6 +785,8 @@ void LLCurl::Multi::easyFree(Easy* easy) void LLCurl::Multi::removeEasy(Easy* easy) { + LLMutexLock lock(mMutexp) ; + check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle())); easyFree(easy); } -- cgit v1.2.3 From 78233d1bf9930575ee7250257ac68603f41f568a Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 5 Dec 2011 17:55:40 -0600 Subject: SH-2652 WIP -- Add timers to relevant areas, pause render pipeline while occlusion queries from previous frame are still pending and perform texture decode work. --- indra/llmessage/llcurl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llmessage/llcurl.cpp') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 7ca25d07fc..ce0632668c 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -841,7 +841,7 @@ LLCurlThread::~LLCurlThread() { } -S32 LLCurlThread::update(U32 max_time_ms) +S32 LLCurlThread::update(F32 max_time_ms) { return LLQueuedThread::update(max_time_ms); } -- cgit v1.2.3 From 50a57ba9fec0435a990338398d5c4f23c5cc91f0 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 9 Dec 2011 12:23:04 -0600 Subject: Backed out changeset fafd857891b1 --- indra/llmessage/llcurl.cpp | 54 +++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 25 deletions(-) (limited to 'indra/llmessage/llcurl.cpp') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 228f039132..7ca25d07fc 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -585,30 +585,37 @@ void LLCurl::Multi::unlock() void LLCurl::Multi::markDead() { - LLMutexLock lock(mDeletionMutexp) ; - + if(mDeletionMutexp) + { + mDeletionMutexp->lock() ; + } + mDead = TRUE ; + + if(mDeletionMutexp) + { + mDeletionMutexp->unlock() ; + } } void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state) { - LLMutexLock lock(mMutexp) ; - + lock() ; mState = state ; if(mState == STATE_READY) { LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_NORMAL) ; } + unlock() ; } LLCurl::Multi::ePerformState LLCurl::Multi::getState() { ePerformState state ; - { - LLMutexLock lock(mMutexp) ; - state = mState ; - } + lock() ; + state = mState ; + unlock() ; return state ; } @@ -628,15 +635,13 @@ bool LLCurl::Multi::waitToComplete() bool completed ; + lock() ; + completed = (STATE_COMPLETED == mState) ; + if(!completed) { - LLMutexLock lock(mMutexp) ; - - completed = (STATE_COMPLETED == mState) ; - if(!completed) - { - LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ; - } + LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ; } + unlock() ; return completed; } @@ -650,8 +655,10 @@ CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue) //return true if dead bool LLCurl::Multi::doPerform() { - LLMutexLock lock(mDeletionMutexp) ; - + if(mDeletionMutexp) + { + mDeletionMutexp->lock() ; + } bool dead = mDead ; if(mDead) @@ -668,8 +675,6 @@ bool LLCurl::Multi::doPerform() call_count < MULTI_PERFORM_CALL_REPEAT; call_count++) { - LLMutexLock lock(mMutexp) ; - CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q); if (CURLM_CALL_MULTI_PERFORM != code || q == 0) { @@ -683,6 +688,11 @@ bool LLCurl::Multi::doPerform() setState(STATE_COMPLETED) ; } + if(mDeletionMutexp) + { + mDeletionMutexp->unlock() ; + } + return dead ; } @@ -754,8 +764,6 @@ LLCurl::Easy* LLCurl::Multi::allocEasy() bool LLCurl::Multi::addEasy(Easy* easy) { - LLMutexLock lock(mMutexp) ; - CURLMcode mcode = curl_multi_add_handle(mCurlMultiHandle, easy->getCurlHandle()); check_curl_multi_code(mcode); //if (mcode != CURLM_OK) @@ -768,8 +776,6 @@ bool LLCurl::Multi::addEasy(Easy* easy) void LLCurl::Multi::easyFree(Easy* easy) { - LLMutexLock lock(mMutexp) ; - mEasyActiveList.erase(easy); mEasyActiveMap.erase(easy->getCurlHandle()); if (mEasyFreeList.size() < EASY_HANDLE_POOL_SIZE) @@ -785,8 +791,6 @@ void LLCurl::Multi::easyFree(Easy* easy) void LLCurl::Multi::removeEasy(Easy* easy) { - LLMutexLock lock(mMutexp) ; - check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle())); easyFree(easy); } -- cgit v1.2.3 From 4ec112bfce19d4bf09ef79b3b3195dda24148730 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Thu, 15 Dec 2011 21:39:48 -0700 Subject: fix for SH-2738 and SH-2777, might also help SH-2723: heap corruption SH-2738: Texture fetching freezes due to LLcurl SH-2777: viewer crashed on logout in LLCurl::Easy::releaseEasyHandle --- indra/llmessage/llcurl.cpp | 63 ++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 25 deletions(-) (limited to 'indra/llmessage/llcurl.cpp') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index ce0632668c..874f4673ca 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -219,11 +219,15 @@ namespace boost std::set LLCurl::Easy::sFreeHandles; std::set LLCurl::Easy::sActiveHandles; +LLMutex* LLCurl::Easy::sHandleMutexp = NULL ; //static CURL* LLCurl::Easy::allocEasyHandle() { CURL* ret = NULL; + + LLMutexLock lock(sHandleMutexp) ; + if (sFreeHandles.empty()) { ret = curl_easy_init(); @@ -251,6 +255,7 @@ void LLCurl::Easy::releaseEasyHandle(CURL* handle) llerrs << "handle cannot be NULL!" << llendl; } + LLMutexLock lock(sHandleMutexp) ; if (sActiveHandles.find(handle) != sActiveHandles.end()) { sActiveHandles.erase(handle); @@ -519,7 +524,8 @@ LLCurl::Multi::Multi() mState(STATE_READY), mDead(FALSE), mMutexp(NULL), - mDeletionMutexp(NULL) + mDeletionMutexp(NULL), + mEasyMutexp(NULL) { mCurlMultiHandle = curl_multi_init(); if (!mCurlMultiHandle) @@ -534,6 +540,7 @@ LLCurl::Multi::Multi() { mMutexp = new LLMutex(NULL) ; mDeletionMutexp = new LLMutex(NULL) ; + mEasyMutexp = new LLMutex(NULL) ; } LLCurl::getCurlThread()->addMulti(this) ; @@ -563,6 +570,8 @@ LLCurl::Multi::~Multi() mMutexp = NULL ; delete mDeletionMutexp ; mDeletionMutexp = NULL ; + delete mEasyMutexp ; + mEasyMutexp = NULL ; --gCurlMultiCount; } @@ -585,17 +594,9 @@ void LLCurl::Multi::unlock() void LLCurl::Multi::markDead() { - if(mDeletionMutexp) - { - mDeletionMutexp->lock() ; - } - + LLMutexLock lock(mDeletionMutexp) ; + mDead = TRUE ; - - if(mDeletionMutexp) - { - mDeletionMutexp->unlock() ; - } } void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state) @@ -655,10 +656,8 @@ CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue) //return true if dead bool LLCurl::Multi::doPerform() { - if(mDeletionMutexp) - { - mDeletionMutexp->lock() ; - } + LLMutexLock lock(mDeletionMutexp) ; + bool dead = mDead ; if(mDead) @@ -675,6 +674,7 @@ bool LLCurl::Multi::doPerform() call_count < MULTI_PERFORM_CALL_REPEAT; call_count++) { + LLMutexLock lock(mMutexp) ; CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q); if (CURLM_CALL_MULTI_PERFORM != code || q == 0) { @@ -688,11 +688,6 @@ bool LLCurl::Multi::doPerform() setState(STATE_COMPLETED) ; } - if(mDeletionMutexp) - { - mDeletionMutexp->unlock() ; - } - return dead ; } @@ -743,19 +738,21 @@ S32 LLCurl::Multi::process() LLCurl::Easy* LLCurl::Multi::allocEasy() { - Easy* easy = 0; + Easy* easy = 0; if (mEasyFreeList.empty()) - { + { easy = Easy::getEasy(); } else { + LLMutexLock lock(mEasyMutexp) ; easy = *(mEasyFreeList.begin()); mEasyFreeList.erase(easy); } if (easy) { + LLMutexLock lock(mEasyMutexp) ; mEasyActiveList.insert(easy); mEasyActiveMap[easy->getCurlHandle()] = easy; } @@ -764,6 +761,7 @@ LLCurl::Easy* LLCurl::Multi::allocEasy() bool LLCurl::Multi::addEasy(Easy* easy) { + LLMutexLock lock(mMutexp) ; CURLMcode mcode = curl_multi_add_handle(mCurlMultiHandle, easy->getCurlHandle()); check_curl_multi_code(mcode); //if (mcode != CURLM_OK) @@ -776,22 +774,30 @@ bool LLCurl::Multi::addEasy(Easy* easy) void LLCurl::Multi::easyFree(Easy* easy) { + mEasyMutexp->lock() ; mEasyActiveList.erase(easy); mEasyActiveMap.erase(easy->getCurlHandle()); + if (mEasyFreeList.size() < EASY_HANDLE_POOL_SIZE) - { - easy->resetState(); + { mEasyFreeList.insert(easy); + mEasyMutexp->unlock() ; + + easy->resetState(); } else { + mEasyMutexp->unlock() ; delete easy; } } void LLCurl::Multi::removeEasy(Easy* easy) { - check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle())); + { + LLMutexLock lock(mMutexp) ; + check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle())); + } easyFree(easy); } @@ -1290,6 +1296,10 @@ void LLCurl::initClass(bool multi_threaded) #endif sCurlThread = new LLCurlThread(multi_threaded) ; + if(multi_threaded) + { + Easy::sHandleMutexp = new LLMutex(NULL) ; + } } void LLCurl::cleanupClass() @@ -1319,6 +1329,9 @@ void LLCurl::cleanupClass() Easy::sFreeHandles.clear(); + delete Easy::sHandleMutexp ; + Easy::sHandleMutexp = NULL ; + llassert(Easy::sActiveHandles.empty()); } -- cgit v1.2.3 From efec138037d7271effd89536d824bec270985909 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Thu, 15 Dec 2011 21:39:48 -0700 Subject: fix for SH-2738 and SH-2777, might also help SH-2723: heap corruption SH-2738: Texture fetching freezes due to LLcurl SH-2777: viewer crashed on logout in LLCurl::Easy::releaseEasyHandle --- indra/llmessage/llcurl.cpp | 63 ++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 25 deletions(-) (limited to 'indra/llmessage/llcurl.cpp') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 7ca25d07fc..d86bf7a0a1 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -219,11 +219,15 @@ namespace boost std::set LLCurl::Easy::sFreeHandles; std::set LLCurl::Easy::sActiveHandles; +LLMutex* LLCurl::Easy::sHandleMutexp = NULL ; //static CURL* LLCurl::Easy::allocEasyHandle() { CURL* ret = NULL; + + LLMutexLock lock(sHandleMutexp) ; + if (sFreeHandles.empty()) { ret = curl_easy_init(); @@ -251,6 +255,7 @@ void LLCurl::Easy::releaseEasyHandle(CURL* handle) llerrs << "handle cannot be NULL!" << llendl; } + LLMutexLock lock(sHandleMutexp) ; if (sActiveHandles.find(handle) != sActiveHandles.end()) { sActiveHandles.erase(handle); @@ -519,7 +524,8 @@ LLCurl::Multi::Multi() mState(STATE_READY), mDead(FALSE), mMutexp(NULL), - mDeletionMutexp(NULL) + mDeletionMutexp(NULL), + mEasyMutexp(NULL) { mCurlMultiHandle = curl_multi_init(); if (!mCurlMultiHandle) @@ -534,6 +540,7 @@ LLCurl::Multi::Multi() { mMutexp = new LLMutex(NULL) ; mDeletionMutexp = new LLMutex(NULL) ; + mEasyMutexp = new LLMutex(NULL) ; } LLCurl::getCurlThread()->addMulti(this) ; @@ -563,6 +570,8 @@ LLCurl::Multi::~Multi() mMutexp = NULL ; delete mDeletionMutexp ; mDeletionMutexp = NULL ; + delete mEasyMutexp ; + mEasyMutexp = NULL ; --gCurlMultiCount; } @@ -585,17 +594,9 @@ void LLCurl::Multi::unlock() void LLCurl::Multi::markDead() { - if(mDeletionMutexp) - { - mDeletionMutexp->lock() ; - } - + LLMutexLock lock(mDeletionMutexp) ; + mDead = TRUE ; - - if(mDeletionMutexp) - { - mDeletionMutexp->unlock() ; - } } void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state) @@ -655,10 +656,8 @@ CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue) //return true if dead bool LLCurl::Multi::doPerform() { - if(mDeletionMutexp) - { - mDeletionMutexp->lock() ; - } + LLMutexLock lock(mDeletionMutexp) ; + bool dead = mDead ; if(mDead) @@ -675,6 +674,7 @@ bool LLCurl::Multi::doPerform() call_count < MULTI_PERFORM_CALL_REPEAT; call_count++) { + LLMutexLock lock(mMutexp) ; CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q); if (CURLM_CALL_MULTI_PERFORM != code || q == 0) { @@ -688,11 +688,6 @@ bool LLCurl::Multi::doPerform() setState(STATE_COMPLETED) ; } - if(mDeletionMutexp) - { - mDeletionMutexp->unlock() ; - } - return dead ; } @@ -743,19 +738,21 @@ S32 LLCurl::Multi::process() LLCurl::Easy* LLCurl::Multi::allocEasy() { - Easy* easy = 0; + Easy* easy = 0; if (mEasyFreeList.empty()) - { + { easy = Easy::getEasy(); } else { + LLMutexLock lock(mEasyMutexp) ; easy = *(mEasyFreeList.begin()); mEasyFreeList.erase(easy); } if (easy) { + LLMutexLock lock(mEasyMutexp) ; mEasyActiveList.insert(easy); mEasyActiveMap[easy->getCurlHandle()] = easy; } @@ -764,6 +761,7 @@ LLCurl::Easy* LLCurl::Multi::allocEasy() bool LLCurl::Multi::addEasy(Easy* easy) { + LLMutexLock lock(mMutexp) ; CURLMcode mcode = curl_multi_add_handle(mCurlMultiHandle, easy->getCurlHandle()); check_curl_multi_code(mcode); //if (mcode != CURLM_OK) @@ -776,22 +774,30 @@ bool LLCurl::Multi::addEasy(Easy* easy) void LLCurl::Multi::easyFree(Easy* easy) { + mEasyMutexp->lock() ; mEasyActiveList.erase(easy); mEasyActiveMap.erase(easy->getCurlHandle()); + if (mEasyFreeList.size() < EASY_HANDLE_POOL_SIZE) - { - easy->resetState(); + { mEasyFreeList.insert(easy); + mEasyMutexp->unlock() ; + + easy->resetState(); } else { + mEasyMutexp->unlock() ; delete easy; } } void LLCurl::Multi::removeEasy(Easy* easy) { - check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle())); + { + LLMutexLock lock(mMutexp) ; + check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle())); + } easyFree(easy); } @@ -1290,6 +1296,10 @@ void LLCurl::initClass(bool multi_threaded) #endif sCurlThread = new LLCurlThread(multi_threaded) ; + if(multi_threaded) + { + Easy::sHandleMutexp = new LLMutex(NULL) ; + } } void LLCurl::cleanupClass() @@ -1319,6 +1329,9 @@ void LLCurl::cleanupClass() Easy::sFreeHandles.clear(); + delete Easy::sHandleMutexp ; + Easy::sHandleMutexp = NULL ; + llassert(Easy::sActiveHandles.empty()); } -- cgit v1.2.3 From 58f9982fbc94ed2f039f0cd32579fa572f87e8ba Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 19 Dec 2011 15:35:38 -0600 Subject: SH-2738 Add comment documenting need to not make main thread wait on curl_multi_perform --- indra/llmessage/llcurl.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indra/llmessage/llcurl.cpp') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 874f4673ca..20f0c6c602 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -675,6 +675,10 @@ bool LLCurl::Multi::doPerform() call_count++) { LLMutexLock lock(mMutexp) ; + + //WARNING: curl_multi_perform will block for many hundreds of milliseconds + // NEVER call this from the main thread, and NEVER allow the main thread to + // wait on a mutex held by this thread while curl_multi_perform is executing CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q); if (CURLM_CALL_MULTI_PERFORM != code || q == 0) { -- cgit v1.2.3 From 43e3603cd763f5f501c8c5dc008d8a00d0744c53 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 19 Dec 2011 16:55:21 -0600 Subject: SH-2738 Don't lock unless we really need to --- indra/llmessage/llcurl.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'indra/llmessage/llcurl.cpp') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index d86bf7a0a1..988c12d6fb 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -612,13 +612,7 @@ void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state) LLCurl::Multi::ePerformState LLCurl::Multi::getState() { - ePerformState state ; - - lock() ; - state = mState ; - unlock() ; - - return state ; + return mState; } bool LLCurl::Multi::isCompleted() @@ -636,14 +630,12 @@ bool LLCurl::Multi::waitToComplete() bool completed ; - lock() ; completed = (STATE_COMPLETED == mState) ; if(!completed) { LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ; } - unlock() ; - + return completed; } -- cgit v1.2.3 From 5affaf264da937cdf825bf174c3905a6063b5336 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 19 Dec 2011 16:55:21 -0600 Subject: SH-2738 Don't lock unless we really need to --- indra/llmessage/llcurl.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'indra/llmessage/llcurl.cpp') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 20f0c6c602..05f3869a11 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -612,13 +612,7 @@ void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state) LLCurl::Multi::ePerformState LLCurl::Multi::getState() { - ePerformState state ; - - lock() ; - state = mState ; - unlock() ; - - return state ; + return mState; } bool LLCurl::Multi::isCompleted() @@ -636,14 +630,12 @@ bool LLCurl::Multi::waitToComplete() bool completed ; - lock() ; completed = (STATE_COMPLETED == mState) ; if(!completed) { LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ; } - unlock() ; - + return completed; } -- cgit v1.2.3 From cfc6ac76e1c700c0810629b005f45747c4144867 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Tue, 20 Dec 2011 11:04:10 -0700 Subject: more tuning of llcurl code targeting crashes like SH-2777. --- indra/llmessage/llcurl.cpp | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) (limited to 'indra/llmessage/llcurl.cpp') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 988c12d6fb..2b351d351e 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -603,11 +603,12 @@ void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state) { lock() ; mState = state ; + unlock() ; + if(mState == STATE_READY) { LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_NORMAL) ; - } - unlock() ; + } } LLCurl::Multi::ePerformState LLCurl::Multi::getState() @@ -628,9 +629,7 @@ bool LLCurl::Multi::waitToComplete() return true ; } - bool completed ; - - completed = (STATE_COMPLETED == mState) ; + bool completed = (STATE_COMPLETED == mState) ; if(!completed) { LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ; @@ -641,6 +640,8 @@ bool LLCurl::Multi::waitToComplete() CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue) { + LLMutexLock lock(mMutexp) ; + CURLMsg* curlmsg = curl_multi_info_read(mCurlMultiHandle, msgs_in_queue); return curlmsg; } @@ -702,10 +703,19 @@ S32 LLCurl::Multi::process() if (msg->msg == CURLMSG_DONE) { U32 response = 0; - easy_active_map_t::iterator iter = mEasyActiveMap.find(msg->easy_handle); - if (iter != mEasyActiveMap.end()) + Easy* easy = NULL ; + + { + LLMutexLock lock(mEasyMutexp) ; + easy_active_map_t::iterator iter = mEasyActiveMap.find(msg->easy_handle); + if (iter != mEasyActiveMap.end()) + { + easy = iter->second; + } + } + + if(easy) { - Easy* easy = iter->second; response = easy->report(msg->data.result); removeEasy(easy); } @@ -766,20 +776,31 @@ bool LLCurl::Multi::addEasy(Easy* easy) void LLCurl::Multi::easyFree(Easy* easy) { - mEasyMutexp->lock() ; + if(mEasyMutexp) + { + mEasyMutexp->lock() ; + } + mEasyActiveList.erase(easy); mEasyActiveMap.erase(easy->getCurlHandle()); if (mEasyFreeList.size() < EASY_HANDLE_POOL_SIZE) { mEasyFreeList.insert(easy); - mEasyMutexp->unlock() ; + + if(mEasyMutexp) + { + mEasyMutexp->unlock() ; + } easy->resetState(); } else { - mEasyMutexp->unlock() ; + if(mEasyMutexp) + { + mEasyMutexp->unlock() ; + } delete easy; } } -- cgit v1.2.3 From 1620ad6d00a77b2089e0ae5f6de30f9a954c6167 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Tue, 20 Dec 2011 11:04:10 -0700 Subject: more tuning of llcurl code targeting crashes like SH-2777. --- indra/llmessage/llcurl.cpp | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) (limited to 'indra/llmessage/llcurl.cpp') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 05f3869a11..5027e8fa84 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -603,11 +603,12 @@ void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state) { lock() ; mState = state ; + unlock() ; + if(mState == STATE_READY) { LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_NORMAL) ; - } - unlock() ; + } } LLCurl::Multi::ePerformState LLCurl::Multi::getState() @@ -628,9 +629,7 @@ bool LLCurl::Multi::waitToComplete() return true ; } - bool completed ; - - completed = (STATE_COMPLETED == mState) ; + bool completed = (STATE_COMPLETED == mState) ; if(!completed) { LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ; @@ -641,6 +640,8 @@ bool LLCurl::Multi::waitToComplete() CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue) { + LLMutexLock lock(mMutexp) ; + CURLMsg* curlmsg = curl_multi_info_read(mCurlMultiHandle, msgs_in_queue); return curlmsg; } @@ -706,10 +707,19 @@ S32 LLCurl::Multi::process() if (msg->msg == CURLMSG_DONE) { U32 response = 0; - easy_active_map_t::iterator iter = mEasyActiveMap.find(msg->easy_handle); - if (iter != mEasyActiveMap.end()) + Easy* easy = NULL ; + + { + LLMutexLock lock(mEasyMutexp) ; + easy_active_map_t::iterator iter = mEasyActiveMap.find(msg->easy_handle); + if (iter != mEasyActiveMap.end()) + { + easy = iter->second; + } + } + + if(easy) { - Easy* easy = iter->second; response = easy->report(msg->data.result); removeEasy(easy); } @@ -770,20 +780,31 @@ bool LLCurl::Multi::addEasy(Easy* easy) void LLCurl::Multi::easyFree(Easy* easy) { - mEasyMutexp->lock() ; + if(mEasyMutexp) + { + mEasyMutexp->lock() ; + } + mEasyActiveList.erase(easy); mEasyActiveMap.erase(easy->getCurlHandle()); if (mEasyFreeList.size() < EASY_HANDLE_POOL_SIZE) { mEasyFreeList.insert(easy); - mEasyMutexp->unlock() ; + + if(mEasyMutexp) + { + mEasyMutexp->unlock() ; + } easy->resetState(); } else { - mEasyMutexp->unlock() ; + if(mEasyMutexp) + { + mEasyMutexp->unlock() ; + } delete easy; } } -- cgit v1.2.3 From ec06aa129f839cc98aaa8006d6467241281da9fa Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Tue, 20 Dec 2011 15:02:21 -0700 Subject: add mutex to protect curl_multi-init() --- indra/llmessage/llcurl.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'indra/llmessage/llcurl.cpp') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 2b351d351e..f569630766 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -517,7 +517,7 @@ void LLCurl::Easy::prepRequest(const std::string& url, } //////////////////////////////////////////////////////////////////////////// - +LLMutex* LLCurl::Multi::sMultiInitMutexp = NULL ; LLCurl::Multi::Multi() : mQueued(0), mErrorCount(0), @@ -527,11 +527,11 @@ LLCurl::Multi::Multi() mDeletionMutexp(NULL), mEasyMutexp(NULL) { - mCurlMultiHandle = curl_multi_init(); + mCurlMultiHandle = initMulti(); if (!mCurlMultiHandle) { llwarns << "curl_multi_init() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl; - mCurlMultiHandle = curl_multi_init(); + mCurlMultiHandle = initMulti(); } llassert_always(mCurlMultiHandle); @@ -576,6 +576,13 @@ LLCurl::Multi::~Multi() --gCurlMultiCount; } +CURLM* LLCurl::Multi::initMulti() +{ + LLMutexLock lock(sMultiInitMutexp) ; + + return curl_multi_init() ; +} + void LLCurl::Multi::lock() { if(mMutexp) @@ -853,11 +860,17 @@ void LLCurlThread::CurlRequest::finishRequest(bool completed) LLCurlThread::LLCurlThread(bool threaded) : LLQueuedThread("curlthread", threaded) { + if(!LLCurl::Multi::sMultiInitMutexp) + { + LLCurl::Multi::sMultiInitMutexp = new LLMutex(NULL) ; + } } //virtual LLCurlThread::~LLCurlThread() { + delete LLCurl::Multi::sMultiInitMutexp ; + LLCurl::Multi::sMultiInitMutexp = NULL ; } S32 LLCurlThread::update(U32 max_time_ms) -- cgit v1.2.3 From f082de03ff24ae8cc6a2de103bc643c392135742 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Thu, 12 Jan 2012 16:36:56 -0700 Subject: fix for SH-2845, SH-2846, SH-2847, SH-2851: curl crashes and out-of-memory crashes. --- indra/llmessage/llcurl.cpp | 293 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 237 insertions(+), 56 deletions(-) (limited to 'indra/llmessage/llcurl.cpp') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index e17380fdf5..eab2874596 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -72,10 +72,12 @@ static const U32 EASY_HANDLE_POOL_SIZE = 5; static const S32 MULTI_PERFORM_CALL_REPEAT = 5; -static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds +static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds per operation static const S32 MAX_ACTIVE_REQUEST_COUNT = 100; -static +static const F32 DEFAULT_MULTI_IDLE_TIME = 120.0f ; //seconds +static const S32 MAX_NUM_OF_HANDLES = 256 ; //max number of handles, (multi handles and easy handles combined). + // DEBUG // S32 gCurlEasyCount = 0; S32 gCurlMultiCount = 0; @@ -87,6 +89,8 @@ std::vector LLCurl::sSSLMutex; std::string LLCurl::sCAPath; std::string LLCurl::sCAFile; LLCurlThread* LLCurl::sCurlThread = NULL ; +LLMutex* LLCurl::sHandleMutexp = NULL ; +S32 LLCurl::sTotalHandles = 0 ; void check_curl_code(CURLcode code) { @@ -230,7 +234,7 @@ CURL* LLCurl::Easy::allocEasyHandle() if (sFreeHandles.empty()) { - ret = curl_easy_init(); + ret = LLCurl::newEasyHandle(); } else { @@ -250,16 +254,27 @@ CURL* LLCurl::Easy::allocEasyHandle() //static void LLCurl::Easy::releaseEasyHandle(CURL* handle) { + static const S32 MAX_NUM_FREE_HANDLES = 32 ; + if (!handle) { - llerrs << "handle cannot be NULL!" << llendl; + return ; //handle allocation failed. + //llerrs << "handle cannot be NULL!" << llendl; } LLMutexLock lock(sHandleMutexp) ; if (sActiveHandles.find(handle) != sActiveHandles.end()) { sActiveHandles.erase(handle); - sFreeHandles.insert(handle); + + if(sFreeHandles.size() < MAX_NUM_FREE_HANDLES) + { + sFreeHandles.insert(handle); + } + else + { + LLCurl::deleteEasyHandle(handle) ; + } } else { @@ -517,8 +532,7 @@ void LLCurl::Easy::prepRequest(const std::string& url, } //////////////////////////////////////////////////////////////////////////// -LLMutex* LLCurl::Multi::sMultiInitMutexp = NULL ; -LLCurl::Multi::Multi() +LLCurl::Multi::Multi(F32 idle_time_out) : mQueued(0), mErrorCount(0), mState(STATE_READY), @@ -527,28 +541,47 @@ LLCurl::Multi::Multi() mDeletionMutexp(NULL), mEasyMutexp(NULL) { - mCurlMultiHandle = initMulti(); + mCurlMultiHandle = LLCurl::newMultiHandle(); if (!mCurlMultiHandle) { llwarns << "curl_multi_init() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl; - mCurlMultiHandle = initMulti(); + mCurlMultiHandle = LLCurl::newMultiHandle(); } - llassert_always(mCurlMultiHandle); - - if(LLCurl::getCurlThread()->getThreaded()) + //llassert_always(mCurlMultiHandle); + + if(mCurlMultiHandle) { - mMutexp = new LLMutex(NULL) ; - mDeletionMutexp = new LLMutex(NULL) ; - mEasyMutexp = new LLMutex(NULL) ; - } - LLCurl::getCurlThread()->addMulti(this) ; + if(LLCurl::getCurlThread()->getThreaded()) + { + mMutexp = new LLMutex(NULL) ; + mDeletionMutexp = new LLMutex(NULL) ; + mEasyMutexp = new LLMutex(NULL) ; + } + LLCurl::getCurlThread()->addMulti(this) ; + + mIdleTimeOut = idle_time_out ; + if(mIdleTimeOut < DEFAULT_MULTI_IDLE_TIME) + { + mIdleTimeOut = DEFAULT_MULTI_IDLE_TIME ; + } - ++gCurlMultiCount; + ++gCurlMultiCount; + } } LLCurl::Multi::~Multi() { + cleanup() ; +} + +void LLCurl::Multi::cleanup() +{ + if(!mCurlMultiHandle) + { + return ; //nothing to clean. + } + // Clean up active for(easy_active_list_t::iterator iter = mEasyActiveList.begin(); iter != mEasyActiveList.end(); ++iter) @@ -564,7 +597,8 @@ LLCurl::Multi::~Multi() for_each(mEasyFreeList.begin(), mEasyFreeList.end(), DeletePointer()); mEasyFreeList.clear(); - check_curl_multi_code(curl_multi_cleanup(mCurlMultiHandle)); + check_curl_multi_code(LLCurl::deleteMultiHandle(mCurlMultiHandle)); + mCurlMultiHandle = NULL ; delete mMutexp ; mMutexp = NULL ; @@ -572,15 +606,13 @@ LLCurl::Multi::~Multi() mDeletionMutexp = NULL ; delete mEasyMutexp ; mEasyMutexp = NULL ; - + + mQueued = 0 ; + mState = STATE_COMPLETED; + --gCurlMultiCount; -} - -CURLM* LLCurl::Multi::initMulti() -{ - LLMutexLock lock(sMultiInitMutexp) ; - return curl_multi_init() ; + return ; } void LLCurl::Multi::lock() @@ -604,6 +636,7 @@ void LLCurl::Multi::markDead() LLMutexLock lock(mDeletionMutexp) ; mDead = TRUE ; + LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ; } void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state) @@ -630,6 +663,11 @@ bool LLCurl::Multi::isCompleted() bool LLCurl::Multi::waitToComplete() { + if(!isValid()) + { + return true ; + } + if(!mMutexp) //not threaded { doPerform() ; @@ -639,7 +677,7 @@ bool LLCurl::Multi::waitToComplete() bool completed = (STATE_COMPLETED == mState) ; if(!completed) { - LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ; + LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_HIGH) ; } return completed; @@ -689,7 +727,12 @@ bool LLCurl::Multi::doPerform() } mQueued = q; - setState(STATE_COMPLETED) ; + setState(STATE_COMPLETED) ; + mIdleTimer.reset() ; + } + else if(mIdleTimer.getElapsedTimeF32() > mIdleTimeOut) //idle for too long, remove it. + { + dead = true ; } return dead ; @@ -697,6 +740,11 @@ bool LLCurl::Multi::doPerform() S32 LLCurl::Multi::process() { + if(!isValid()) + { + return 0 ; + } + waitToComplete() ; if (getState() != STATE_COMPLETED) @@ -849,7 +897,11 @@ bool LLCurlThread::CurlRequest::processRequest() if(mMulti) { completed = mCurlThread->doMultiPerform(mMulti) ; - setPriority(LLQueuedThread::PRIORITY_LOW) ; + + if(!completed) + { + setPriority(LLQueuedThread::PRIORITY_LOW) ; + } } return completed ; @@ -857,24 +909,26 @@ bool LLCurlThread::CurlRequest::processRequest() void LLCurlThread::CurlRequest::finishRequest(bool completed) { - mCurlThread->deleteMulti(mMulti) ; + if(mMulti->isDead()) + { + mCurlThread->deleteMulti(mMulti) ; + } + else + { + mMulti->cleanup() ; //being idle too long, remove the request. + } + mMulti = NULL ; } LLCurlThread::LLCurlThread(bool threaded) : LLQueuedThread("curlthread", threaded) { - if(!LLCurl::Multi::sMultiInitMutexp) - { - LLCurl::Multi::sMultiInitMutexp = new LLMutex(NULL) ; - } } //virtual LLCurlThread::~LLCurlThread() { - delete LLCurl::Multi::sMultiInitMutexp ; - LLCurl::Multi::sMultiInitMutexp = NULL ; } S32 LLCurlThread::update(F32 max_time_ms) @@ -896,7 +950,19 @@ void LLCurlThread::addMulti(LLCurl::Multi* multi) void LLCurlThread::killMulti(LLCurl::Multi* multi) { - multi->markDead() ; + if(!multi) + { + return ; + } + + if(multi->isValid()) + { + multi->markDead() ; + } + else + { + deleteMulti(multi) ; + } } //private @@ -942,7 +1008,14 @@ LLCurlRequest::~LLCurlRequest() void LLCurlRequest::addMulti() { LLCurl::Multi* multi = new LLCurl::Multi(); - + if(!multi->isValid()) + { + LLCurl::getCurlThread()->killMulti(multi) ; + mActiveMulti = NULL ; + mActiveRequestCount = 0 ; + return; + } + mMultiSet.insert(multi); mActiveMulti = multi; mActiveRequestCount = 0; @@ -1066,6 +1139,19 @@ S32 LLCurlRequest::process() { curlmulti_set_t::iterator curiter = iter++; LLCurl::Multi* multi = *curiter; + + if(!multi->isValid()) + { + if(multi == mActiveMulti) + { + mActiveMulti = NULL ; + mActiveRequestCount = 0 ; + } + mMultiSet.erase(curiter) ; + LLCurl::getCurlThread()->killMulti(multi) ; + continue ; + } + S32 tres = multi->process(); res += tres; if (multi != mActiveMulti && tres == 0 && multi->mQueued == 0) @@ -1086,6 +1172,19 @@ S32 LLCurlRequest::getQueued() { curlmulti_set_t::iterator curiter = iter++; LLCurl::Multi* multi = *curiter; + + if(!multi->isValid()) + { + if(multi == mActiveMulti) + { + mActiveMulti = NULL ; + mActiveRequestCount = 0 ; + } + LLCurl::getCurlThread()->killMulti(multi); + mMultiSet.erase(curiter) ; + continue ; + } + queued += multi->mQueued; if (multi->getState() != LLCurl::Multi::STATE_READY) { @@ -1105,13 +1204,22 @@ LLCurlEasyRequest::LLCurlEasyRequest() { mMulti = new LLCurl::Multi(); - mEasy = mMulti->allocEasy(); - if (mEasy) + if(mMulti->isValid()) { - mEasy->setErrorBuffer(); - mEasy->setCA(); - // Set proxy settings if configured to do so. - LLProxy::getInstance()->applyProxySettings(mEasy); + mEasy = mMulti->allocEasy(); + if (mEasy) + { + mEasy->setErrorBuffer(); + mEasy->setCA(); + // Set proxy settings if configured to do so. + LLProxy::getInstance()->applyProxySettings(mEasy); + } + } + else + { + LLCurl::getCurlThread()->killMulti(mMulti) ; + mEasy = NULL ; + mMulti = NULL ; } } @@ -1122,7 +1230,7 @@ LLCurlEasyRequest::~LLCurlEasyRequest() void LLCurlEasyRequest::setopt(CURLoption option, S32 value) { - if (mEasy) + if (isValid() && mEasy) { mEasy->setopt(option, value); } @@ -1130,7 +1238,7 @@ void LLCurlEasyRequest::setopt(CURLoption option, S32 value) void LLCurlEasyRequest::setoptString(CURLoption option, const std::string& value) { - if (mEasy) + if (isValid() && mEasy) { mEasy->setoptString(option, value); } @@ -1138,7 +1246,7 @@ void LLCurlEasyRequest::setoptString(CURLoption option, const std::string& value void LLCurlEasyRequest::setPost(char* postdata, S32 size) { - if (mEasy) + if (isValid() && mEasy) { mEasy->setopt(CURLOPT_POST, 1); mEasy->setopt(CURLOPT_POSTFIELDS, postdata); @@ -1148,7 +1256,7 @@ void LLCurlEasyRequest::setPost(char* postdata, S32 size) void LLCurlEasyRequest::setHeaderCallback(curl_header_callback callback, void* userdata) { - if (mEasy) + if (isValid() && mEasy) { mEasy->setopt(CURLOPT_HEADERFUNCTION, (void*)callback); mEasy->setopt(CURLOPT_HEADERDATA, userdata); // aka CURLOPT_WRITEHEADER @@ -1157,7 +1265,7 @@ void LLCurlEasyRequest::setHeaderCallback(curl_header_callback callback, void* u void LLCurlEasyRequest::setWriteCallback(curl_write_callback callback, void* userdata) { - if (mEasy) + if (isValid() && mEasy) { mEasy->setopt(CURLOPT_WRITEFUNCTION, (void*)callback); mEasy->setopt(CURLOPT_WRITEDATA, userdata); @@ -1166,7 +1274,7 @@ void LLCurlEasyRequest::setWriteCallback(curl_write_callback callback, void* use void LLCurlEasyRequest::setReadCallback(curl_read_callback callback, void* userdata) { - if (mEasy) + if (isValid() && mEasy) { mEasy->setopt(CURLOPT_READFUNCTION, (void*)callback); mEasy->setopt(CURLOPT_READDATA, userdata); @@ -1175,7 +1283,7 @@ void LLCurlEasyRequest::setReadCallback(curl_read_callback callback, void* userd void LLCurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void* userdata) { - if (mEasy) + if (isValid() && mEasy) { mEasy->setopt(CURLOPT_SSL_CTX_FUNCTION, (void*)callback); mEasy->setopt(CURLOPT_SSL_CTX_DATA, userdata); @@ -1184,7 +1292,7 @@ void LLCurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void* void LLCurlEasyRequest::slist_append(const char* str) { - if (mEasy) + if (isValid() && mEasy) { mEasy->slist_append(str); } @@ -1195,7 +1303,7 @@ void LLCurlEasyRequest::sendRequest(const std::string& url) llassert_always(!mRequestSent); mRequestSent = true; lldebugs << url << llendl; - if (mEasy) + if (isValid() && mEasy) { mEasy->setHeaders(); mEasy->setoptString(CURLOPT_URL, url); @@ -1207,7 +1315,7 @@ void LLCurlEasyRequest::requestComplete() { llassert_always(mRequestSent); mRequestSent = false; - if (mEasy) + if (isValid() && mEasy) { mMulti->removeEasy(mEasy); } @@ -1216,6 +1324,10 @@ void LLCurlEasyRequest::requestComplete() // Usage: Call getRestult until it returns false (no more messages) bool LLCurlEasyRequest::getResult(CURLcode* result, LLCurl::TransferInfo* info) { + if(!isValid()) + { + return false ; + } if (!mMulti->isCompleted()) { //we're busy, try again later return false; @@ -1280,7 +1392,7 @@ CURLMsg* LLCurlEasyRequest::info_read(S32* q, LLCurl::TransferInfo* info) std::string LLCurlEasyRequest::getErrorString() { - return mEasy ? std::string(mEasy->getErrorBuffer()) : std::string(); + return isValid() && mEasy ? std::string(mEasy->getErrorBuffer()) : std::string(); } //////////////////////////////////////////////////////////////////////////// @@ -1328,6 +1440,7 @@ void LLCurl::initClass(bool multi_threaded) sCurlThread = new LLCurlThread(multi_threaded) ; if(multi_threaded) { + sHandleMutexp = new LLMutex(NULL) ; Easy::sHandleMutexp = new LLMutex(NULL) ; } } @@ -1354,7 +1467,7 @@ void LLCurl::cleanupClass() for (std::set::iterator iter = Easy::sFreeHandles.begin(); iter != Easy::sFreeHandles.end(); ++iter) { CURL* curl = *iter; - curl_easy_cleanup(curl); + LLCurl::deleteEasyHandle(curl); } Easy::sFreeHandles.clear(); @@ -1362,9 +1475,77 @@ void LLCurl::cleanupClass() delete Easy::sHandleMutexp ; Easy::sHandleMutexp = NULL ; + delete sHandleMutexp ; + sHandleMutexp = NULL ; + llassert(Easy::sActiveHandles.empty()); } +//static +CURLM* LLCurl::newMultiHandle() +{ + LLMutexLock lock(sHandleMutexp) ; + + if(sTotalHandles + 1 > MAX_NUM_OF_HANDLES) + { + llwarns << "no more handles available." << llendl ; + return NULL ; //failed + } + sTotalHandles++; + + CURLM* ret = curl_multi_init() ; + if(!ret) + { + llwarns << "curl_multi_init failed." << llendl ; + } + + return ret ; +} + +//static +CURLMcode LLCurl::deleteMultiHandle(CURLM* handle) +{ + if(handle) + { + LLMutexLock lock(sHandleMutexp) ; + sTotalHandles-- ; + return curl_multi_cleanup(handle) ; + } + return CURLM_OK ; +} + +//static +CURL* LLCurl::newEasyHandle() +{ + LLMutexLock lock(sHandleMutexp) ; + + if(sTotalHandles + 1 > MAX_NUM_OF_HANDLES) + { + llwarns << "no more handles available." << llendl ; + return NULL ; //failed + } + sTotalHandles++; + + CURL* ret = curl_easy_init() ; + if(!ret) + { + llwarns << "curl_easy_init failed." << llendl ; + } + + return ret ; +} + +//static +void LLCurl::deleteEasyHandle(CURL* handle) +{ + if(handle) + { + LLMutexLock lock(sHandleMutexp) ; + curl_easy_cleanup(handle) ; + sTotalHandles-- ; + } +} + const unsigned int LLCurl::MAX_REDIRECTS = 5; // Provide access to LLCurl free functions outside of llcurl.cpp without polluting the global namespace. -- cgit v1.2.3 From 11bd5cb86025376a198e45330116de4757b5c89e Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Thu, 12 Jan 2012 20:32:32 -0700 Subject: trivial: fix a mac build error. --- indra/llmessage/llcurl.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'indra/llmessage/llcurl.cpp') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index eab2874596..277c274f52 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -915,7 +915,7 @@ void LLCurlThread::CurlRequest::finishRequest(bool completed) } else { - mMulti->cleanup() ; //being idle too long, remove the request. + mCurlThread->cleanupMulti(mMulti) ; //being idle too long, remove the request. } mMulti = NULL ; @@ -976,6 +976,13 @@ void LLCurlThread::deleteMulti(LLCurl::Multi* multi) { delete multi ; } + +//private +void LLCurlThread::cleanupMulti(LLCurl::Multi* multi) +{ + multi->cleanup() ; +} + //------------------------------------------------------------ //static -- cgit v1.2.3 From 25c21c3761d871fa7927e2a5656ed18100084454 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Tue, 17 Jan 2012 22:56:28 -0700 Subject: add more exception handlings for llcurl fix. --- indra/llmessage/llcurl.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'indra/llmessage/llcurl.cpp') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 277c274f52..5edf0dc8c0 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -1036,7 +1036,12 @@ LLCurl::Easy* LLCurlRequest::allocEasy() { addMulti(); } - llassert_always(mActiveMulti); + if(!mActiveMulti) + { + return NULL ; + } + + //llassert_always(mActiveMulti); ++mActiveRequestCount; LLCurl::Easy* easy = mActiveMulti->allocEasy(); return easy; -- cgit v1.2.3 From 9e6a5d721193f181c39e58fe00073bece74b081a Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Fri, 20 Jan 2012 11:55:15 -0700 Subject: fix for SH-2823 and SH-2824: LLCurl crash inside LLBufferArray::countAfter() and LLBufferArray::copyIntoBuffers --- indra/llmessage/llcurl.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'indra/llmessage/llcurl.cpp') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 5edf0dc8c0..1ab82a273b 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -228,6 +228,8 @@ LLMutex* LLCurl::Easy::sHandleMutexp = NULL ; //static CURL* LLCurl::Easy::allocEasyHandle() { + llassert(LLCurl::getCurlThread()) ; + CURL* ret = NULL; LLMutexLock lock(sHandleMutexp) ; @@ -489,6 +491,7 @@ void LLCurl::Easy::prepRequest(const std::string& url, LLProxy::getInstance()->applyProxySettings(this); mOutput.reset(new LLBufferArray); + mOutput->setThreaded(true); setopt(CURLOPT_WRITEFUNCTION, (void*)&curlWriteCallback); setopt(CURLOPT_WRITEDATA, (void*)this); -- cgit v1.2.3 From 1316f3313066beef74729c2be5a8d142d185161d Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Wed, 25 Jan 2012 16:01:56 -0700 Subject: fix for SH-2904: textures remain stuck in HTP state --- indra/llmessage/llcurl.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'indra/llmessage/llcurl.cpp') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 1ab82a273b..32a9cd061f 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -91,6 +91,7 @@ std::string LLCurl::sCAFile; LLCurlThread* LLCurl::sCurlThread = NULL ; LLMutex* LLCurl::sHandleMutexp = NULL ; S32 LLCurl::sTotalHandles = 0 ; +bool LLCurl::sNotQuitting = true; void check_curl_code(CURLcode code) { @@ -319,6 +320,14 @@ LLCurl::Easy::~Easy() --gCurlEasyCount; curl_slist_free_all(mHeaders); for_each(mStrings.begin(), mStrings.end(), DeletePointerArray()); + + if (mResponder && LLCurl::sNotQuitting) //aborted + { + std::string reason("Request timeout, aborted.") ; + mResponder->completedRaw(408, //HTTP_REQUEST_TIME_OUT, timeout, abort + reason, mChannels, mOutput); + } + mResponder = NULL; } void LLCurl::Easy::resetState() @@ -1462,6 +1471,8 @@ void LLCurl::initClass(bool multi_threaded) void LLCurl::cleanupClass() { + sNotQuitting = false; //set quitting + //shut down curl thread while(1) { -- cgit v1.2.3 From 717a6f3306d9382ea252c3e0f243b785c9cae15a Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Wed, 25 Jan 2012 18:27:40 -0700 Subject: Introduce two new parameters "CurlUseMultipleThreads" and "CurlRequestTimeOut" for QA to test Curl. --- indra/llmessage/llcurl.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'indra/llmessage/llcurl.cpp') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 32a9cd061f..3bcaffc275 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -75,9 +75,6 @@ static const S32 MULTI_PERFORM_CALL_REPEAT = 5; static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds per operation static const S32 MAX_ACTIVE_REQUEST_COUNT = 100; -static const F32 DEFAULT_MULTI_IDLE_TIME = 120.0f ; //seconds -static const S32 MAX_NUM_OF_HANDLES = 256 ; //max number of handles, (multi handles and easy handles combined). - // DEBUG // S32 gCurlEasyCount = 0; S32 gCurlMultiCount = 0; @@ -92,6 +89,8 @@ LLCurlThread* LLCurl::sCurlThread = NULL ; LLMutex* LLCurl::sHandleMutexp = NULL ; S32 LLCurl::sTotalHandles = 0 ; bool LLCurl::sNotQuitting = true; +F32 LLCurl::sCurlRequestTimeOut = 120.f; //seonds +S32 LLCurl::sMaxHandles = 256; //max number of handles, (multi handles and easy handles combined). void check_curl_code(CURLcode code) { @@ -573,9 +572,9 @@ LLCurl::Multi::Multi(F32 idle_time_out) LLCurl::getCurlThread()->addMulti(this) ; mIdleTimeOut = idle_time_out ; - if(mIdleTimeOut < DEFAULT_MULTI_IDLE_TIME) + if(mIdleTimeOut < LLCurl::sCurlRequestTimeOut) { - mIdleTimeOut = DEFAULT_MULTI_IDLE_TIME ; + mIdleTimeOut = LLCurl::sCurlRequestTimeOut ; } ++gCurlMultiCount; @@ -1442,8 +1441,11 @@ unsigned long LLCurl::ssl_thread_id(void) } #endif -void LLCurl::initClass(bool multi_threaded) +void LLCurl::initClass(F32 curl_reuest_timeout, S32 max_number_handles, bool multi_threaded) { + sCurlRequestTimeOut = curl_reuest_timeout ; //seconds + sMaxHandles = max_number_handles ; //max number of handles, (multi handles and easy handles combined). + // 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 @@ -1512,7 +1514,7 @@ CURLM* LLCurl::newMultiHandle() { LLMutexLock lock(sHandleMutexp) ; - if(sTotalHandles + 1 > MAX_NUM_OF_HANDLES) + if(sTotalHandles + 1 > sMaxHandles) { llwarns << "no more handles available." << llendl ; return NULL ; //failed @@ -1545,7 +1547,7 @@ CURL* LLCurl::newEasyHandle() { LLMutexLock lock(sHandleMutexp) ; - if(sTotalHandles + 1 > MAX_NUM_OF_HANDLES) + if(sTotalHandles + 1 > sMaxHandles) { llwarns << "no more handles available." << llendl ; return NULL ; //failed -- cgit v1.2.3 From 5a14a67e060e7f325025e924c83489cfa236e3dc Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Wed, 1 Feb 2012 13:03:46 -0800 Subject: converted a bunch of narrowing implicit conversions to explicit --- indra/llmessage/llcurl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/llmessage/llcurl.cpp') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index e17380fdf5..344463f036 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -428,9 +428,9 @@ size_t curlReadCallback(char* data, size_t size, size_t nmemb, void* user_data) LLCurl::Easy* easy = (LLCurl::Easy*)user_data; S32 n = size * nmemb; - S32 startpos = easy->getInput().tellg(); + S32 startpos = (S32)easy->getInput().tellg(); easy->getInput().seekg(0, std::ios::end); - S32 endpos = easy->getInput().tellg(); + S32 endpos = (S32)easy->getInput().tellg(); easy->getInput().seekg(startpos, std::ios::beg); S32 maxn = endpos - startpos; n = llmin(n, maxn); -- cgit v1.2.3