From 4331c112aba074562e9a8826fe6d271a94f790f0 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 14 Oct 2011 11:52:40 -0500 Subject: Backed out changeset b782a75c99e6 --- indra/llmessage/llurlrequest.cpp | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'indra/llmessage/llurlrequest.cpp') diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index 83b6f7cf71..cb9d1c3731 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -40,7 +40,6 @@ #include "llstring.h" #include "apr_env.h" #include "llapr.h" -#include "llscopedvolatileaprpool.h" static const U32 HTTP_STATUS_PIPE_ERROR = 499; /** @@ -211,31 +210,27 @@ void LLURLRequest::setCallback(LLURLRequestComplete* callback) // is called with use_proxy = FALSE void LLURLRequest::useProxy(bool use_proxy) { - static std::string env_proxy; + static char *env_proxy; - if (use_proxy && env_proxy.empty()) + if (use_proxy && (env_proxy == NULL)) { - char* env_proxy_str; - LLScopedVolatileAPRPool scoped_pool; - apr_status_t status = apr_env_get(&env_proxy_str, "ALL_PROXY", scoped_pool); + apr_status_t status; + LLAPRPool pool; + status = apr_env_get(&env_proxy, "ALL_PROXY", pool.getAPRPool()); if (status != APR_SUCCESS) { - status = apr_env_get(&env_proxy_str, "http_proxy", scoped_pool); + status = apr_env_get(&env_proxy, "http_proxy", pool.getAPRPool()); } if (status != APR_SUCCESS) { - use_proxy = false; + use_proxy = FALSE; } - else - { - // env_proxy_str is stored in the scoped_pool, so we have to make a copy. - env_proxy = env_proxy_str; - } } - lldebugs << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = \"" << env_proxy << "\"" << llendl; - if (use_proxy) + lldebugs << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (env_proxy ? env_proxy : "(null)") << llendl; + + if (env_proxy && use_proxy) { mDetail->mCurlRequest->setoptString(CURLOPT_PROXY, env_proxy); } -- cgit v1.3 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 +++++++++++++++++++++------------- 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(-) (limited to 'indra/llmessage/llurlrequest.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; 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& headers, ResponderPtr, S32 time_out = 0, bool post = false); + void prepRequest(const std::string& url, const std::vector& 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 mStrings; - ResponderPtr mResponder; + LLCurl::ResponderPtr mResponder; static std::set sFreeHandles; static std::set 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_active_list_t; + typedef std::set easy_active_list_t; easy_active_list_t mEasyActiveList; - typedef std::map easy_active_map_t; + typedef std::map easy_active_map_t; easy_active_map_t mEasyActiveMap; - typedef std::set easy_free_list_t; + typedef std::set 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.3 From 94ad019ce3387b9c5207fe3207933697059dd2dd Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Wed, 4 Jan 2012 14:14:23 -0700 Subject: fix for SH-2823 and SH-2824: crash in curl: LLBufferArray::countAfter() and LLBufferArray::copyIntoBuffers reviewed by vir --- indra/llmessage/llurlrequest.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'indra/llmessage/llurlrequest.cpp') diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index a3a2b2b1b8..261e57e79e 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -64,7 +64,7 @@ public: ~LLURLRequestDetail(); std::string mURL; LLCurlEasyRequest* mCurlRequest; - LLBufferArray* mResponseBuffer; + LLIOPipe::buffer_ptr_t mResponseBuffer; LLChannelDescriptors mChannels; U8* mLastRead; U32 mBodyLimit; @@ -75,7 +75,6 @@ public: LLURLRequestDetail::LLURLRequestDetail() : mCurlRequest(NULL), - mResponseBuffer(NULL), mLastRead(NULL), mBodyLimit(0), mByteAccumulator(0), @@ -90,7 +89,6 @@ LLURLRequestDetail::~LLURLRequestDetail() { LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); delete mCurlRequest; - mResponseBuffer = NULL; mLastRead = NULL; } @@ -326,7 +324,7 @@ LLIOPipe::EStatus LLURLRequest::process_impl( // *FIX: bit of a hack, but it should work. The configure and // callback method expect this information to be ready. - mDetail->mResponseBuffer = buffer.get(); + mDetail->mResponseBuffer = buffer; mDetail->mChannels = channels; if(!configure()) { -- cgit v1.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 +++++++++++++++++---- indra/llmessage/llcurl.h | 22 +- indra/llmessage/llhttpassetstorage.cpp | 10 +- indra/llmessage/llhttpclient.cpp | 12 +- indra/llmessage/lliopipe.cpp | 6 + indra/llmessage/lliopipe.h | 2 + indra/llmessage/llpumpio.cpp | 50 +++- indra/llmessage/llpumpio.h | 12 +- indra/llmessage/llsdrpcclient.h | 3 + indra/llmessage/llurlrequest.cpp | 18 ++ indra/llmessage/llurlrequest.h | 2 + indra/newview/llmeshrepository.cpp | 131 +++++---- indra/newview/llmeshrepository.h | 4 +- indra/newview/llxmlrpctransaction.cpp | 19 ++ .../updater/llupdatedownloader.cpp | 23 +- 15 files changed, 475 insertions(+), 132 deletions(-) (limited to 'indra/llmessage/llurlrequest.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. diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 9c2c215c7a..32da911cbf 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -43,6 +43,7 @@ #include "llsd.h" #include "llthread.h" #include "llqueuedthread.h" +#include "llframetimer.h" class LLMutex; class LLCurlThread; @@ -182,11 +183,20 @@ public: static unsigned long ssl_thread_id(void); static LLCurlThread* getCurlThread() { return sCurlThread ;} + + static CURLM* newMultiHandle() ; + static CURLMcode deleteMultiHandle(CURLM* handle) ; + static CURL* newEasyHandle() ; + static void deleteEasyHandle(CURL* handle) ; + private: static std::string sCAPath; static std::string sCAFile; static const unsigned int MAX_REDIRECTS; static LLCurlThread* sCurlThread; + + static LLMutex* sHandleMutexp ; + static S32 sTotalHandles ; }; class LLCurl::Easy @@ -277,7 +287,7 @@ public: STATE_COMPLETED=2 } ePerformState; - Multi(); + Multi(F32 idle_time_out = 0.f); LLCurl::Easy* allocEasy(); bool addEasy(LLCurl::Easy* easy); @@ -288,7 +298,10 @@ public: void setState(ePerformState state) ; ePerformState getState() ; + bool isCompleted() ; + bool isValid() {return mCurlMultiHandle != NULL ;} + bool isDead() {return mDead;} bool waitToComplete() ; @@ -299,9 +312,9 @@ public: S32 mQueued; S32 mErrorCount; - static CURLM* initMulti() ; private: void easyFree(LLCurl::Easy*); + void cleanup() ; CURLM* mCurlMultiHandle; @@ -319,8 +332,8 @@ private: LLMutex* mMutexp ; LLMutex* mDeletionMutexp ; LLMutex* mEasyMutexp ; - - static LLMutex* sMultiInitMutexp ; + LLFrameTimer mIdleTimer ; + F32 mIdleTimeOut; }; class LLCurlThread : public LLQueuedThread @@ -414,6 +427,7 @@ public: std::string getErrorString(); bool isCompleted() {return mMulti->isCompleted() ;} bool wait() { return mMulti->waitToComplete(); } + bool isValid() {return mMulti && mMulti->isValid(); } LLCurl::Easy* getEasy() const { return mEasy; } diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp index 2bca517e97..612d765969 100644 --- a/indra/llmessage/llhttpassetstorage.cpp +++ b/indra/llmessage/llhttpassetstorage.cpp @@ -232,7 +232,8 @@ LLSD LLHTTPAssetRequest::getFullDetails() const void LLHTTPAssetRequest::setupCurlHandle() { // *NOTE: Similar code exists in mapserver/llcurlutil.cpp JC - mCurlHandle = curl_easy_init(); + mCurlHandle = LLCurl::newEasyHandle(); + llassert_always(mCurlHandle != NULL) ; // Apply proxy settings if configured to do so LLProxy::getInstance()->applyProxySettings(mCurlHandle); @@ -278,7 +279,7 @@ void LLHTTPAssetRequest::setupCurlHandle() void LLHTTPAssetRequest::cleanupCurlHandle() { - curl_easy_cleanup(mCurlHandle); + LLCurl::deleteEasyHandle(mCurlHandle); if (mAssetStoragep) { // Terminating a request. Thus upload or download is no longer pending. @@ -429,12 +430,13 @@ void LLHTTPAssetStorage::_init(const std::string& web_host, const std::string& l // curl_global_init moved to LLCurl::initClass() - mCurlMultiHandle = curl_multi_init(); + mCurlMultiHandle = LLCurl::newMultiHandle() ; + llassert_always(mCurlMultiHandle != NULL) ; } LLHTTPAssetStorage::~LLHTTPAssetStorage() { - curl_multi_cleanup(mCurlMultiHandle); + LLCurl::deleteMultiHandle(mCurlMultiHandle); mCurlMultiHandle = NULL; // curl_global_cleanup moved to LLCurl::initClass() diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index dd4e3a6300..231cb7ca8f 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -228,6 +228,12 @@ static void request( LLPumpIO::chain_t chain; LLURLRequest* req = new LLURLRequest(method, url); + if(!req->isValid())//failed + { + delete req ; + return ; + } + req->setSSLVerifyCallback(LLHTTPClient::getCertVerifyCallback(), (void *)req); @@ -423,7 +429,9 @@ static LLSD blocking_request( { lldebugs << "blockingRequest of " << url << llendl; char curl_error_buffer[CURL_ERROR_SIZE] = "\0"; - CURL* curlp = curl_easy_init(); + CURL* curlp = LLCurl::newEasyHandle(); + llassert_always(curlp != NULL) ; + LLHTTPBuffer http_buffer; std::string body_str; @@ -517,7 +525,7 @@ static LLSD blocking_request( } // * Cleanup - curl_easy_cleanup(curlp); + LLCurl::deleteEasyHandle(curlp); return response; } diff --git a/indra/llmessage/lliopipe.cpp b/indra/llmessage/lliopipe.cpp index 6e4eec74a6..8f827f7a30 100644 --- a/indra/llmessage/lliopipe.cpp +++ b/indra/llmessage/lliopipe.cpp @@ -75,6 +75,12 @@ LLIOPipe::~LLIOPipe() //lldebugs << "destroying LLIOPipe" << llendl; } +//virtual +bool LLIOPipe::isValid() +{ + return true ; +} + // static std::string LLIOPipe::lookupStatusString(EStatus status) { diff --git a/indra/llmessage/lliopipe.h b/indra/llmessage/lliopipe.h index 8e656b6da1..cbd17b5a3d 100644 --- a/indra/llmessage/lliopipe.h +++ b/indra/llmessage/lliopipe.h @@ -231,6 +231,8 @@ public: */ virtual ~LLIOPipe(); + virtual bool isValid() ; + protected: /** * @brief Base Constructor. diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp index a8d2a0a224..0ff300efd0 100644 --- a/indra/llmessage/llpumpio.cpp +++ b/indra/llmessage/llpumpio.cpp @@ -195,7 +195,7 @@ bool LLPumpIO::prime(apr_pool_t* pool) return ((pool == NULL) ? false : true); } -bool LLPumpIO::addChain(const chain_t& chain, F32 timeout) +bool LLPumpIO::addChain(const chain_t& chain, F32 timeout, bool has_curl_request) { LLMemType m1(LLMemType::MTYPE_IO_PUMP); if(chain.empty()) return false; @@ -204,6 +204,7 @@ bool LLPumpIO::addChain(const chain_t& chain, F32 timeout) LLScopedLock lock(mChainsMutex); #endif LLChainInfo info; + info.mHasCurlRequest = has_curl_request; info.setTimeoutSeconds(timeout); info.mData = LLIOPipe::buffer_ptr_t(new LLBufferArray); LLLinkInfo link; @@ -440,6 +441,15 @@ void LLPumpIO::pump() static LLFastTimer::DeclareTimer FTM_PUMP_IO("Pump IO"); +LLPumpIO::current_chain_t LLPumpIO::removeRunningChain(LLPumpIO::current_chain_t& run_chain) +{ + std::for_each( + (*run_chain).mDescriptors.begin(), + (*run_chain).mDescriptors.end(), + ll_delete_apr_pollset_fd_client_data()); + return mRunningChains.erase(run_chain); +} + //timeout is in microseconds void LLPumpIO::pump(const S32& poll_timeout) { @@ -585,10 +595,16 @@ void LLPumpIO::pump(const S32& poll_timeout) // << (*run_chain).mChainLinks[0].mPipe // << " because we reached the end." << llendl; #endif - run_chain = mRunningChains.erase(run_chain); + run_chain = removeRunningChain(run_chain); continue; } } + else if(isChainExpired(*run_chain)) + { + run_chain = removeRunningChain(run_chain); + continue; + } + PUMP_DEBUG; if((*run_chain).mLock) { @@ -696,11 +712,7 @@ void LLPumpIO::pump(const S32& poll_timeout) PUMP_DEBUG; // This chain is done. Clean up any allocated memory and // erase the chain info. - std::for_each( - (*run_chain).mDescriptors.begin(), - (*run_chain).mDescriptors.end(), - ll_delete_apr_pollset_fd_client_data()); - run_chain = mRunningChains.erase(run_chain); + run_chain = removeRunningChain(run_chain); // *NOTE: may not always need to rebuild the pollset. mRebuildPollset = true; @@ -1095,6 +1107,24 @@ void LLPumpIO::processChain(LLChainInfo& chain) PUMP_DEBUG; } +bool LLPumpIO::isChainExpired(LLChainInfo& chain) +{ + if(!chain.mHasCurlRequest) + { + return false ; + } + + for(links_t::iterator iter = chain.mChainLinks.begin(); iter != chain.mChainLinks.end(); ++iter) + { + if(!(*iter).mPipe->isValid()) + { + return true ; + } + } + + return false ; +} + bool LLPumpIO::handleChainError( LLChainInfo& chain, LLIOPipe::EStatus error) @@ -1136,6 +1166,9 @@ bool LLPumpIO::handleChainError( #endif keep_going = false; break; + case LLIOPipe::STATUS_EXPIRED: + keep_going = false; + break ; default: if(LLIOPipe::isSuccess(error)) { @@ -1157,7 +1190,8 @@ bool LLPumpIO::handleChainError( LLPumpIO::LLChainInfo::LLChainInfo() : mInit(false), mLock(0), - mEOS(false) + mEOS(false), + mHasCurlRequest(false) { LLMemType m1(LLMemType::MTYPE_IO_PUMP); mTimer.setTimerExpirySec(DEFAULT_CHAIN_EXPIRY_SECS); diff --git a/indra/llmessage/llpumpio.h b/indra/llmessage/llpumpio.h index 9303c9d7fc..e405124403 100644 --- a/indra/llmessage/llpumpio.h +++ b/indra/llmessage/llpumpio.h @@ -113,7 +113,7 @@ public: * expire. Pass in 0.0f to never expire. * @return Returns true if anything was added to the pump. */ - bool addChain(const chain_t& chain, F32 timeout); + bool addChain(const chain_t& chain, F32 timeout, bool has_curl_request = false); /** * @brief Struct to associate a pipe with it's buffer io indexes. @@ -356,12 +356,13 @@ protected: // basic member data bool mInit; + bool mEOS; + bool mHasCurlRequest; S32 mLock; LLFrameTimer mTimer; links_t::iterator mHead; links_t mChainLinks; - LLIOPipe::buffer_ptr_t mData; - bool mEOS; + LLIOPipe::buffer_ptr_t mData; LLSD mContext; // tracking inside the pump @@ -402,7 +403,7 @@ protected: protected: void initialize(apr_pool_t* pool); void cleanup(); - + current_chain_t removeRunningChain(current_chain_t& chain) ; /** * @brief Given the internal state of the chains, rebuild the pollset * @see setConditional() @@ -429,6 +430,9 @@ protected: */ bool handleChainError(LLChainInfo& chain, LLIOPipe::EStatus error); + //if the chain is expired, remove it + bool isChainExpired(LLChainInfo& chain) ; + public: /** * @brief Return number of running chains. diff --git a/indra/llmessage/llsdrpcclient.h b/indra/llmessage/llsdrpcclient.h index 9fb49a5c33..235077179e 100644 --- a/indra/llmessage/llsdrpcclient.h +++ b/indra/llmessage/llsdrpcclient.h @@ -239,6 +239,8 @@ public: LLSDRPCClientFactory(const std::string& fixed_url) : mURL(fixed_url) {} virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const { + llerrs << "Can not call this." << llendl ; + lldebugs << "LLSDRPCClientFactory::build" << llendl; LLIOPipe::ptr_t service(new Client); chain.push_back(service); @@ -282,6 +284,7 @@ public: LLXMLSDRPCClientFactory(const std::string& fixed_url) : mURL(fixed_url) {} virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const { + llerrs << "who calls this?" << llendl ; lldebugs << "LLXMLSDRPCClientFactory::build" << llendl; LLIOPipe::ptr_t service(new Client); chain.push_back(service); diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index 261e57e79e..f02c636838 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -83,6 +83,12 @@ LLURLRequestDetail::LLURLRequestDetail() : { LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); mCurlRequest = new LLCurlEasyRequest(); + + if(!mCurlRequest->isValid()) //failed. + { + delete mCurlRequest ; + mCurlRequest = NULL ; + } } LLURLRequestDetail::~LLURLRequestDetail() @@ -250,12 +256,24 @@ void LLURLRequest::allowCookies() mDetail->mCurlRequest->setoptString(CURLOPT_COOKIEFILE, ""); } +//virtual +bool LLURLRequest::isValid() +{ + return mDetail->mCurlRequest && mDetail->mCurlRequest->isValid(); +} + // virtual LLIOPipe::EStatus LLURLRequest::handleError( LLIOPipe::EStatus status, LLPumpIO* pump) { LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); + + if(!isValid()) + { + return STATUS_EXPIRED ; + } + if(mCompletionCallback && pump) { LLURLRequestComplete* complete = NULL; diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h index ec5c2c1941..44d358d906 100644 --- a/indra/llmessage/llurlrequest.h +++ b/indra/llmessage/llurlrequest.h @@ -188,6 +188,8 @@ public: */ void allowCookies(); + /*virtual*/ bool isValid() ; + public: /** * @brief Give this pipe a chance to handle a generated error diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index a97e256c89..c64479f589 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -498,9 +498,11 @@ void LLMeshRepoThread::run() LODRequest req = mLODReqQ.front(); mLODReqQ.pop(); mMutex->unlock(); - if (fetchMeshLOD(req.mMeshParams, req.mLOD)) + if (!fetchMeshLOD(req.mMeshParams, req.mLOD, count))//failed, resubmit { - count++; + mMutex->lock(); + mLODReqQ.push(req) ; + mMutex->unlock(); } } } @@ -512,9 +514,11 @@ void LLMeshRepoThread::run() HeaderRequest req = mHeaderReqQ.front(); mHeaderReqQ.pop(); mMutex->unlock(); - if (fetchMeshHeader(req.mMeshParams)) + if (!fetchMeshHeader(req.mMeshParams, count))//failed, resubmit { - count++; + mMutex->lock(); + mHeaderReqQ.push(req) ; + mMutex->unlock(); } } } @@ -658,6 +662,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) return false; } + bool ret = true ; U32 header_size = mMeshHeaderSize[mesh_id]; if (header_size > 0) @@ -673,7 +678,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) //check VFS for mesh skin info LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH); if (file.getSize() >= offset+size) - { + { LLMeshRepository::sCacheBytesRead += size; file.seek(offset); U8* buffer = new U8[size]; @@ -689,7 +694,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) if (!zero) { //attempt to parse if (skinInfoReceived(mesh_id, buffer, size)) - { + { delete[] buffer; return true; } @@ -704,11 +709,14 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) std::string http_url = constructUrl(mesh_id); if (!http_url.empty()) - { - ++sActiveLODRequests; - LLMeshRepository::sHTTPRequestCount++; - mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size, + { + ret = mCurlRequest->getByteRange(http_url, headers, offset, size, new LLMeshSkinInfoResponder(mesh_id, offset, size)); + if(ret) + { + ++sActiveLODRequests; + LLMeshRepository::sHTTPRequestCount++; + } } } } @@ -718,7 +726,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) } //early out was not hit, effectively fetched - return true; + return ret; } bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) @@ -732,7 +740,8 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) } U32 header_size = mMeshHeaderSize[mesh_id]; - + bool ret = true ; + if (header_size > 0) { S32 version = mMeshHeader[mesh_id]["version"].asInteger(); @@ -748,6 +757,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) if (file.getSize() >= offset+size) { LLMeshRepository::sCacheBytesRead += size; + file.seek(offset); U8* buffer = new U8[size]; file.read(buffer, size); @@ -777,11 +787,14 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) std::string http_url = constructUrl(mesh_id); if (!http_url.empty()) - { - ++sActiveLODRequests; - LLMeshRepository::sHTTPRequestCount++; - mCurlRequest->getByteRange(http_url, headers, offset, size, + { + ret = mCurlRequest->getByteRange(http_url, headers, offset, size, new LLMeshDecompositionResponder(mesh_id, offset, size)); + if(ret) + { + ++sActiveLODRequests; + LLMeshRepository::sHTTPRequestCount++; + } } } } @@ -791,7 +804,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) } //early out was not hit, effectively fetched - return true; + return ret; } bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) @@ -805,6 +818,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) } U32 header_size = mMeshHeaderSize[mesh_id]; + bool ret = true ; if (header_size > 0) { @@ -850,11 +864,15 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) std::string http_url = constructUrl(mesh_id); if (!http_url.empty()) - { - ++sActiveLODRequests; - LLMeshRepository::sHTTPRequestCount++; - mCurlRequest->getByteRange(http_url, headers, offset, size, + { + ret = mCurlRequest->getByteRange(http_url, headers, offset, size, new LLMeshPhysicsShapeResponder(mesh_id, offset, size)); + + if(ret) + { + ++sActiveLODRequests; + LLMeshRepository::sHTTPRequestCount++; + } } } else @@ -868,13 +886,12 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) } //early out was not hit, effectively fetched - return true; + return ret; } -bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params) +//return false if failed to get header +bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, U32& count) { - bool retval = false; - { //look for mesh in asset in vfs LLVFile file(gVFS, mesh_params.getSculptID(), LLAssetType::AT_MESH); @@ -889,36 +906,40 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params) file.read(buffer, bytes); if (headerReceived(mesh_params, buffer, bytes)) { //did not do an HTTP request, return false - return false; + return true; } } } - //either cache entry doesn't exist or is corrupt, request header from simulator - + //either cache entry doesn't exist or is corrupt, request header from simulator + bool retval = true ; std::vector headers; headers.push_back("Accept: application/octet-stream"); std::string http_url = constructUrl(mesh_params.getSculptID()); if (!http_url.empty()) { - ++sActiveHeaderRequests; - retval = true; //grab first 4KB if we're going to bother with a fetch. Cache will prevent future fetches if a full mesh fits //within the first 4KB - //NOTE -- this will break of headers ever exceed 4KB - LLMeshRepository::sHTTPRequestCount++; - mCurlRequest->getByteRange(http_url, headers, 0, 4096, new LLMeshHeaderResponder(mesh_params)); + //NOTE -- this will break of headers ever exceed 4KB + retval = mCurlRequest->getByteRange(http_url, headers, 0, 4096, new LLMeshHeaderResponder(mesh_params)); + if(retval) + { + ++sActiveHeaderRequests; + LLMeshRepository::sHTTPRequestCount++; + } + count++; } return retval; } -bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod) +//return false if failed to get mesh lod. +bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, U32& count) { //protected by mMutex mHeaderMutex->lock(); - bool retval = false; + bool retval = true; LLUUID mesh_id = mesh_params.getSculptID(); @@ -955,7 +976,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod) if (lodReceived(mesh_params, lod, buffer, size)) { delete[] buffer; - return false; + return true; } } @@ -968,12 +989,16 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod) std::string http_url = constructUrl(mesh_id); if (!http_url.empty()) - { - ++sActiveLODRequests; - retval = true; - LLMeshRepository::sHTTPRequestCount++; - mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size, + { + retval = mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size, new LLMeshLODResponder(mesh_params, lod, offset, size)); + + if(retval) + { + ++sActiveLODRequests; + LLMeshRepository::sHTTPRequestCount++; + } + count++; } else { @@ -1540,8 +1565,17 @@ void LLMeshUploadThread::doWholeModelUpload() LLSD body = full_model_data["asset_resources"]; dump_llsd_to_file(body,make_dump_name("whole_model_body_",dump_num)); LLCurlRequest::headers_t headers; - mCurlRequest->post(mWholeModelUploadURL, headers, body, - new LLWholeModelUploadResponder(this, full_model_data, mUploadObserverHandle), mMeshUploadTimeOut); + + { + LLCurl::ResponderPtr responder = new LLWholeModelUploadResponder(this, full_model_data, mUploadObserverHandle) ; + + while(!mCurlRequest->post(mWholeModelUploadURL, headers, body, responder, mMeshUploadTimeOut)) + { + //sleep for 10ms to prevent eating a whole core + apr_sleep(10000); + } + } + do { mCurlRequest->process(); @@ -1571,8 +1605,15 @@ void LLMeshUploadThread::requestWholeModelFee() mPendingUploads++; LLCurlRequest::headers_t headers; - mCurlRequest->post(mWholeModelFeeCapability, headers, model_data, - new LLWholeModelFeeResponder(this,model_data, mFeeObserverHandle), mMeshUploadTimeOut); + + { + LLCurl::ResponderPtr responder = new LLWholeModelFeeResponder(this,model_data, mFeeObserverHandle) ; + while(!mCurlRequest->post(mWholeModelFeeCapability, headers, model_data, responder, mMeshUploadTimeOut)) + { + //sleep for 10ms to prevent eating a whole core + apr_sleep(10000); + } + } do { diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 31b84ea0d9..2efe810438 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -323,8 +323,8 @@ public: virtual void run(); void loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod); - bool fetchMeshHeader(const LLVolumeParams& mesh_params); - bool fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod); + bool fetchMeshHeader(const LLVolumeParams& mesh_params, U32& count); + bool fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, U32& count); bool headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size); bool lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size); bool skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size); diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index 920a9a3752..0da70d398b 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -305,6 +305,15 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip) { mCurlRequest = new LLCurlEasyRequest(); } + if(!mCurlRequest->isValid()) + { + llwarns << "mCurlRequest is invalid." << llendl ; + + delete mCurlRequest ; + mCurlRequest = NULL ; + return ; + } + mErrorCert = NULL; // mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // useful for debugging @@ -357,10 +366,20 @@ LLXMLRPCTransaction::Impl::~Impl() } delete mCurlRequest; + mCurlRequest = NULL ; } bool LLXMLRPCTransaction::Impl::process() { + if(!mCurlRequest || !mCurlRequest->isValid()) + { + llwarns << "transaction failed." << llendl ; + + delete mCurlRequest ; + mCurlRequest = NULL ; + return true ; //failed, quit. + } + switch(mStatus) { case LLXMLRPCTransaction::StatusComplete: diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index e88d1bf811..19ac418e9e 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -39,7 +39,7 @@ #include "llsdserialize.h" #include "llthread.h" #include "llupdaterservice.h" - +#include "llcurl.h" class LLUpdateDownloader::Implementation: public LLThread @@ -198,13 +198,19 @@ LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & LLUpdateDownloader::Implementation::~Implementation() { - if(isDownloading()) { + if(isDownloading()) + { cancel(); shutdown(); - } else { + } + else + { ; // No op. } - if(mCurl) curl_easy_cleanup(mCurl); + if(mCurl) + { + LLCurl::deleteEasyHandle(mCurl); + } } @@ -406,9 +412,12 @@ void LLUpdateDownloader::Implementation::run(void) void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & url, bool processHeader) { - if(mCurl == 0) { - mCurl = curl_easy_init(); - } else { + if(mCurl == 0) + { + mCurl = LLCurl::newEasyHandle(); + } + else + { curl_easy_reset(mCurl); } -- cgit v1.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 ++++++- indra/llmessage/llurlrequest.cpp | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'indra/llmessage/llurlrequest.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; diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index f02c636838..a16f5c7bf0 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -459,6 +459,12 @@ void LLURLRequest::initialize() LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); mState = STATE_INITIALIZED; mDetail = new LLURLRequestDetail; + + if(!isValid()) + { + return ; + } + mDetail->mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1); mDetail->mCurlRequest->setWriteCallback(&downCallback, (void*)this); mDetail->mCurlRequest->setReadCallback(&upCallback, (void*)this); -- cgit v1.3