diff options
Diffstat (limited to 'indra/llmessage/llcurl.cpp')
-rw-r--r-- | indra/llmessage/llcurl.cpp | 119 |
1 files changed, 99 insertions, 20 deletions
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 7c8b7e3584..0735842dcd 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -579,11 +579,18 @@ void LLCurl::Easy::prepRequest(const std::string& url, //////////////////////////////////////////////////////////////////////////// -class LLCurl::Multi +class LLCurl::Multi : public LLThread { LOG_CLASS(Multi); public: - + + typedef enum + { + PERFORM_STATE_READY=0, + PERFORM_STATE_PERFORMING=1, + PERFORM_STATE_COMPLETED=2 + } ePerformState; + Multi(); ~Multi(); @@ -593,13 +600,20 @@ public: void removeEasy(Easy* easy); S32 process(); - S32 perform(); + void perform(); + virtual void run(); + CURLMsg* info_read(S32* msgs_in_queue); S32 mQueued; S32 mErrorCount; + S32 mPerformState; + + LLCondition* mSignal; + bool mQuitting; + private: void easyFree(Easy*); @@ -614,9 +628,14 @@ private: }; LLCurl::Multi::Multi() - : mQueued(0), - mErrorCount(0) + : LLThread("Curl Multi"), + mQueued(0), + mErrorCount(0), + mPerformState(PERFORM_STATE_READY) { + mQuitting = false; + mSignal = new LLCondition(NULL); + mCurlMultiHandle = curl_multi_init(); if (!mCurlMultiHandle) { @@ -630,6 +649,11 @@ LLCurl::Multi::Multi() LLCurl::Multi::~Multi() { + llassert(isStopped()); + + delete mSignal; + mSignal = NULL; + // Clean up active for(easy_active_list_t::iterator iter = mEasyActiveList.begin(); iter != mEasyActiveList.end(); ++iter) @@ -655,30 +679,50 @@ CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue) return curlmsg; } +void LLCurl::Multi::perform() +{ + if (mPerformState == PERFORM_STATE_READY) + { + mSignal->signal(); + } +} -S32 LLCurl::Multi::perform() +void LLCurl::Multi::run() { - S32 q = 0; - for (S32 call_count = 0; - call_count < MULTI_PERFORM_CALL_REPEAT; - call_count += 1) + while (!mQuitting) { - CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q); - if (CURLM_CALL_MULTI_PERFORM != code || q == 0) + mSignal->wait(); + mPerformState = PERFORM_STATE_PERFORMING; + if (!mQuitting) { - check_curl_multi_code(code); - break; - } + 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; + } } - mQueued = q; - return q; } S32 LLCurl::Multi::process() { perform(); - + + if (mPerformState != PERFORM_STATE_COMPLETED) + { + return 0; + } + CURLMsg* msg; int msgs_in_queue; @@ -709,6 +753,8 @@ S32 LLCurl::Multi::process() } } } + + mPerformState = PERFORM_STATE_READY; return processed; } @@ -787,6 +833,18 @@ LLCurlRequest::LLCurlRequest() : 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; + while (!multi->isStopped()) + { + multi->mSignal->signal(); + apr_sleep(1000); + } + } for_each(mMultiSet.begin(), mMultiSet.end(), DeletePointer()); } @@ -794,6 +852,7 @@ void LLCurlRequest::addMulti() { llassert_always(mThreadID == LLThread::currentID()); LLCurl::Multi* multi = new LLCurl::Multi(); + multi->start(); mMultiSet.insert(multi); mActiveMulti = multi; mActiveRequestCount = 0; @@ -923,6 +982,13 @@ S32 LLCurlRequest::process() if (multi != mActiveMulti && tres == 0 && multi->mQueued == 0) { mMultiSet.erase(curiter); + multi->mQuitting = true; + while (!multi->isStopped()) + { + multi->mSignal->signal(); + apr_sleep(1000); + } + delete multi; } } @@ -953,6 +1019,7 @@ LLCurlEasyRequest::LLCurlEasyRequest() mResultReturned(false) { mMulti = new LLCurl::Multi(); + mMulti->start(); mEasy = mMulti->allocEasy(); if (mEasy) { @@ -963,6 +1030,12 @@ LLCurlEasyRequest::LLCurlEasyRequest() LLCurlEasyRequest::~LLCurlEasyRequest() { + mMulti->mQuitting = true; + while (!mMulti->isStopped()) + { + mMulti->mSignal->signal(); + apr_sleep(1000); + } delete mMulti; } @@ -1059,14 +1132,20 @@ void LLCurlEasyRequest::requestComplete() } } -S32 LLCurlEasyRequest::perform() +void LLCurlEasyRequest::perform() { - return mMulti->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) + { //we're busy, try again later + return false; + } + mMulti->mPerformState = LLCurl::Multi::PERFORM_STATE_READY; + if (!mEasy) { // Special case - we failed to initialize a curl_easy (can happen if too many open files) |