From 764a13a196fb66bf4b3fe4fcf98625a385e99e6e Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 21 Jul 2011 17:35:04 -0500 Subject: SH-2031 Don't do network I/O from the main thread in llcurl. Reviewed by Kelly --- indra/llmessage/llcurl.cpp | 65 +++++++++++++++++++++++++++++------ indra/llmessage/llcurl.h | 2 +- indra/llmessage/llfiltersd2xmlrpc.cpp | 12 +++++++ indra/llmessage/lliohttpserver.cpp | 9 +++++ indra/llmessage/lliosocket.cpp | 7 ++++ indra/llmessage/llioutil.cpp | 5 +++ indra/llmessage/llsdrpcclient.cpp | 6 ++++ indra/llmessage/llsdrpcserver.cpp | 3 ++ indra/llmessage/llurlrequest.cpp | 36 +++++++++++++++++-- 9 files changed, 131 insertions(+), 14 deletions(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 7c8b7e3584..453ffa9db9 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,17 @@ 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; + private: void easyFree(Easy*); @@ -614,8 +625,10 @@ private: }; LLCurl::Multi::Multi() - : mQueued(0), - mErrorCount(0) + : LLThread("Curl Multi"), + mQueued(0), + mErrorCount(0), + mPerformState(PERFORM_STATE_READY) { mCurlMultiHandle = curl_multi_init(); if (!mCurlMultiHandle) @@ -630,6 +643,7 @@ LLCurl::Multi::Multi() LLCurl::Multi::~Multi() { + llassert(isStopped()); // Clean up active for(easy_active_list_t::iterator iter = mEasyActiveList.begin(); iter != mEasyActiveList.end(); ++iter) @@ -655,8 +669,16 @@ CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue) return curlmsg; } +void LLCurl::Multi::perform() +{ + if (mPerformState == PERFORM_STATE_READY) + { + mPerformState = PERFORM_STATE_PERFORMING; + start(); + } +} -S32 LLCurl::Multi::perform() +void LLCurl::Multi::run() { S32 q = 0; for (S32 call_count = 0; @@ -672,13 +694,18 @@ S32 LLCurl::Multi::perform() } mQueued = q; - return q; + mPerformState = PERFORM_STATE_COMPLETED; } S32 LLCurl::Multi::process() { perform(); - + + if (mPerformState != PERFORM_STATE_COMPLETED) + { + return 0; + } + CURLMsg* msg; int msgs_in_queue; @@ -709,6 +736,8 @@ S32 LLCurl::Multi::process() } } } + + mPerformState = PERFORM_STATE_READY; return processed; } @@ -923,6 +952,12 @@ S32 LLCurlRequest::process() if (multi != mActiveMulti && tres == 0 && multi->mQueued == 0) { mMultiSet.erase(curiter); + + while (!multi->isStopped()) + { + apr_sleep(1000); + } + delete multi; } } @@ -963,6 +998,10 @@ LLCurlEasyRequest::LLCurlEasyRequest() LLCurlEasyRequest::~LLCurlEasyRequest() { + while (!mMulti->isStopped()) + { + apr_sleep(1000); + } delete mMulti; } @@ -1059,14 +1098,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) diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 4ce3fa1078..2f951d6ab8 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -236,7 +236,7 @@ public: void slist_append(const char* str); void sendRequest(const std::string& url); void requestComplete(); - S32 perform(); + void perform(); bool getResult(CURLcode* result, LLCurl::TransferInfo* info = NULL); std::string getErrorString(); diff --git a/indra/llmessage/llfiltersd2xmlrpc.cpp b/indra/llmessage/llfiltersd2xmlrpc.cpp index 812ef7c151..e0ca056a5f 100644 --- a/indra/llmessage/llfiltersd2xmlrpc.cpp +++ b/indra/llmessage/llfiltersd2xmlrpc.cpp @@ -308,6 +308,7 @@ LLFilterSD2XMLRPCResponse::~LLFilterSD2XMLRPCResponse() } +static LLFastTimer::DeclareTimer FTM_PROCESS_SD2XMLRPC_RESPONSE("SD2XMLRPC Response"); // virtual LLIOPipe::EStatus LLFilterSD2XMLRPCResponse::process_impl( const LLChannelDescriptors& channels, @@ -316,6 +317,8 @@ LLIOPipe::EStatus LLFilterSD2XMLRPCResponse::process_impl( LLSD& context, LLPumpIO* pump) { + LLFastTimer t(FTM_PROCESS_SD2XMLRPC_RESPONSE); + PUMP_DEBUG; // This pipe does not work if it does not have everyting. This // could be addressed by making a stream parser for llsd which @@ -382,6 +385,8 @@ LLFilterSD2XMLRPCRequest::~LLFilterSD2XMLRPCRequest() { } +static LLFastTimer::DeclareTimer FTM_PROCESS_SD2XMLRPC_REQUEST("S22XMLRPC Request"); + // virtual LLIOPipe::EStatus LLFilterSD2XMLRPCRequest::process_impl( const LLChannelDescriptors& channels, @@ -390,6 +395,7 @@ LLIOPipe::EStatus LLFilterSD2XMLRPCRequest::process_impl( LLSD& context, LLPumpIO* pump) { + LLFastTimer t(FTM_PROCESS_SD2XMLRPC_REQUEST); // This pipe does not work if it does not have everyting. This // could be addressed by making a stream parser for llsd which // handled partial information. @@ -586,6 +592,8 @@ LLFilterXMLRPCResponse2LLSD::~LLFilterXMLRPCResponse2LLSD() { } +static LLFastTimer::DeclareTimer FTM_PROCESS_XMLRPC2LLSD_RESPONSE("XMLRPC2LLSD Response"); + LLIOPipe::EStatus LLFilterXMLRPCResponse2LLSD::process_impl( const LLChannelDescriptors& channels, buffer_ptr_t& buffer, @@ -593,6 +601,8 @@ LLIOPipe::EStatus LLFilterXMLRPCResponse2LLSD::process_impl( LLSD& context, LLPumpIO* pump) { + LLFastTimer t(FTM_PROCESS_XMLRPC2LLSD_RESPONSE); + PUMP_DEBUG; if(!eos) return STATUS_BREAK; if(!buffer) return STATUS_ERROR; @@ -668,6 +678,7 @@ LLFilterXMLRPCRequest2LLSD::~LLFilterXMLRPCRequest2LLSD() { } +static LLFastTimer::DeclareTimer FTM_PROCESS_XMLRPC2LLSD_REQUEST("XMLRPC2LLSD Request"); LLIOPipe::EStatus LLFilterXMLRPCRequest2LLSD::process_impl( const LLChannelDescriptors& channels, buffer_ptr_t& buffer, @@ -675,6 +686,7 @@ LLIOPipe::EStatus LLFilterXMLRPCRequest2LLSD::process_impl( LLSD& context, LLPumpIO* pump) { + LLFastTimer t(FTM_PROCESS_XMLRPC2LLSD_REQUEST); PUMP_DEBUG; if(!eos) return STATUS_BREAK; if(!buffer) return STATUS_ERROR; diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp index 3b18a9177c..73e8a69085 100644 --- a/indra/llmessage/lliohttpserver.cpp +++ b/indra/llmessage/lliohttpserver.cpp @@ -140,6 +140,7 @@ private: LLSD mHeaders; }; +static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_PIPE("HTTP Pipe"); LLIOPipe::EStatus LLHTTPPipe::process_impl( const LLChannelDescriptors& channels, buffer_ptr_t& buffer, @@ -147,6 +148,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl( LLSD& context, LLPumpIO* pump) { + LLFastTimer t(FTM_PROCESS_HTTP_PIPE); PUMP_DEBUG; lldebugs << "LLSDHTTPServer::process_impl" << llendl; @@ -428,6 +430,9 @@ protected: /** * LLHTTPResponseHeader */ + +static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_HEADER("HTTP Header"); + // virtual LLIOPipe::EStatus LLHTTPResponseHeader::process_impl( const LLChannelDescriptors& channels, @@ -436,6 +441,7 @@ LLIOPipe::EStatus LLHTTPResponseHeader::process_impl( LLSD& context, LLPumpIO* pump) { + LLFastTimer t(FTM_PROCESS_HTTP_HEADER); PUMP_DEBUG; LLMemType m1(LLMemType::MTYPE_IO_HTTP_SERVER); if(eos) @@ -630,6 +636,8 @@ void LLHTTPResponder::markBad( << "\n\n"; } +static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_RESPONDER("HTTP Responder"); + // virtual LLIOPipe::EStatus LLHTTPResponder::process_impl( const LLChannelDescriptors& channels, @@ -638,6 +646,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl( LLSD& context, LLPumpIO* pump) { + LLFastTimer t(FTM_PROCESS_HTTP_RESPONDER); PUMP_DEBUG; LLMemType m1(LLMemType::MTYPE_IO_HTTP_SERVER); LLIOPipe::EStatus status = STATUS_OK; diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp index 8c752fbe30..b717e321bf 100644 --- a/indra/llmessage/lliosocket.cpp +++ b/indra/llmessage/lliosocket.cpp @@ -301,6 +301,8 @@ LLIOSocketReader::~LLIOSocketReader() //lldebugs << "Destroying LLIOSocketReader" << llendl; } +static LLFastTimer::DeclareTimer FTM_PROCESS_SOCKET_READER("Socket Reader"); + // virtual LLIOPipe::EStatus LLIOSocketReader::process_impl( const LLChannelDescriptors& channels, @@ -309,6 +311,7 @@ LLIOPipe::EStatus LLIOSocketReader::process_impl( LLSD& context, LLPumpIO* pump) { + LLFastTimer t(FTM_PROCESS_SOCKET_READER); PUMP_DEBUG; LLMemType m1(LLMemType::MTYPE_IO_TCP); if(!mSource) return STATUS_PRECONDITION_NOT_MET; @@ -401,6 +404,7 @@ LLIOSocketWriter::~LLIOSocketWriter() //lldebugs << "Destroying LLIOSocketWriter" << llendl; } +static LLFastTimer::DeclareTimer FTM_PROCESS_SOCKET_WRITER("Socket Writer"); // virtual LLIOPipe::EStatus LLIOSocketWriter::process_impl( const LLChannelDescriptors& channels, @@ -409,6 +413,7 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl( LLSD& context, LLPumpIO* pump) { + LLFastTimer t(FTM_PROCESS_SOCKET_WRITER); PUMP_DEBUG; LLMemType m1(LLMemType::MTYPE_IO_TCP); if(!mDestination) return STATUS_PRECONDITION_NOT_MET; @@ -555,6 +560,7 @@ void LLIOServerSocket::setResponseTimeout(F32 timeout_secs) mResponseTimeout = timeout_secs; } +static LLFastTimer::DeclareTimer FTM_PROCESS_SERVER_SOCKET("Server Socket"); // virtual LLIOPipe::EStatus LLIOServerSocket::process_impl( const LLChannelDescriptors& channels, @@ -563,6 +569,7 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl( LLSD& context, LLPumpIO* pump) { + LLFastTimer t(FTM_PROCESS_SERVER_SOCKET); PUMP_DEBUG; LLMemType m1(LLMemType::MTYPE_IO_TCP); if(!pump) diff --git a/indra/llmessage/llioutil.cpp b/indra/llmessage/llioutil.cpp index 2e6ee59ff2..8c50fd5069 100644 --- a/indra/llmessage/llioutil.cpp +++ b/indra/llmessage/llioutil.cpp @@ -43,6 +43,8 @@ LLIOPipe::EStatus LLIOFlush::process_impl( return STATUS_OK; } + +static LLFastTimer::DeclareTimer FTM_PROCESS_SLEEP("IO Sleep"); /** * @class LLIOSleep */ @@ -53,6 +55,7 @@ LLIOPipe::EStatus LLIOSleep::process_impl( LLSD& context, LLPumpIO* pump) { + LLFastTimer t(FTM_PROCESS_SLEEP); if(mSeconds > 0.0) { if(pump) pump->sleepChain(mSeconds); @@ -62,6 +65,7 @@ LLIOPipe::EStatus LLIOSleep::process_impl( return STATUS_DONE; } +static LLFastTimer::DeclareTimer FTM_PROCESS_ADD_CHAIN("Add Chain"); /** * @class LLIOAddChain */ @@ -72,6 +76,7 @@ LLIOPipe::EStatus LLIOAddChain::process_impl( LLSD& context, LLPumpIO* pump) { + LLFastTimer t(FTM_PROCESS_ADD_CHAIN); pump->addChain(mChain, mTimeout); return STATUS_DONE; } diff --git a/indra/llmessage/llsdrpcclient.cpp b/indra/llmessage/llsdrpcclient.cpp index 86fe5c7912..91fd070f07 100644 --- a/indra/llmessage/llsdrpcclient.cpp +++ b/indra/llmessage/llsdrpcclient.cpp @@ -82,6 +82,8 @@ bool LLSDRPCResponse::extractResponse(const LLSD& sd) return rv; } +static LLFastTimer::DeclareTimer FTM_SDRPC_RESPONSE("SDRPC Response"); + // virtual LLIOPipe::EStatus LLSDRPCResponse::process_impl( const LLChannelDescriptors& channels, @@ -90,6 +92,7 @@ LLIOPipe::EStatus LLSDRPCResponse::process_impl( LLSD& context, LLPumpIO* pump) { + LLFastTimer t(FTM_SDRPC_RESPONSE); PUMP_DEBUG; LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT); if(mIsError) @@ -178,6 +181,8 @@ bool LLSDRPCClient::call( return true; } +static LLFastTimer::DeclareTimer FTM_PROCESS_SDRPC_CLIENT("SDRPC Client"); + // virtual LLIOPipe::EStatus LLSDRPCClient::process_impl( const LLChannelDescriptors& channels, @@ -186,6 +191,7 @@ LLIOPipe::EStatus LLSDRPCClient::process_impl( LLSD& context, LLPumpIO* pump) { + LLFastTimer t(FTM_PROCESS_SDRPC_CLIENT); PUMP_DEBUG; LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT); if((STATE_NONE == mState) || (!pump)) diff --git a/indra/llmessage/llsdrpcserver.cpp b/indra/llmessage/llsdrpcserver.cpp index f87c418fb1..9f776aca72 100644 --- a/indra/llmessage/llsdrpcserver.cpp +++ b/indra/llmessage/llsdrpcserver.cpp @@ -97,6 +97,8 @@ void LLSDRPCServer::clearLock() } } +static LLFastTimer::DeclareTimer FTM_PROCESS_SDRPC_SERVER("SDRPC Server"); + // virtual LLIOPipe::EStatus LLSDRPCServer::process_impl( const LLChannelDescriptors& channels, @@ -105,6 +107,7 @@ LLIOPipe::EStatus LLSDRPCServer::process_impl( LLSD& context, LLPumpIO* pump) { + LLFastTimer t(FTM_PROCESS_SDRPC_SERVER); PUMP_DEBUG; LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER); // lldebugs << "LLSDRPCServer::process_impl" << llendl; diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index 28bd09fc4c..e8e35d00a2 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -270,6 +270,8 @@ LLIOPipe::EStatus LLURLRequest::handleError( return status; } +static LLFastTimer::DeclareTimer FTM_PROCESS_URL_REQUEST("URL Request"); + // virtual LLIOPipe::EStatus LLURLRequest::process_impl( const LLChannelDescriptors& channels, @@ -278,6 +280,7 @@ LLIOPipe::EStatus LLURLRequest::process_impl( LLSD& context, LLPumpIO* pump) { + LLFastTimer t(FTM_PROCESS_URL_REQUEST); PUMP_DEBUG; LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); //llinfos << "LLURLRequest::process_impl()" << llendl; @@ -288,6 +291,8 @@ LLIOPipe::EStatus LLURLRequest::process_impl( const S32 MIN_ACCUMULATION = 100000; if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION)) { + static LLFastTimer::DeclareTimer FTM_URL_ADJUST_TIMEOUT("Adjust Timeout"); + LLFastTimer t(FTM_URL_ADJUST_TIMEOUT); // This is a pretty sloppy calculation, but this // tries to make the gross assumption that if data // is coming in at 56kb/s, then this transfer will @@ -335,16 +340,30 @@ LLIOPipe::EStatus LLURLRequest::process_impl( { PUMP_DEBUG; LLIOPipe::EStatus status = STATUS_BREAK; - mDetail->mCurlRequest->perform(); + static LLFastTimer::DeclareTimer FTM_URL_PERFORM("Perform"); + { + LLFastTimer t(FTM_URL_PERFORM); + mDetail->mCurlRequest->perform(); + } + while(1) { CURLcode result; - bool newmsg = mDetail->mCurlRequest->getResult(&result); + + static LLFastTimer::DeclareTimer FTM_PROCESS_URL_REQUEST_GET_RESULT("Get Result"); + + bool newmsg = false; + { + LLFastTimer t(FTM_PROCESS_URL_REQUEST_GET_RESULT); + newmsg = mDetail->mCurlRequest->getResult(&result); + } + if(!newmsg) { // keep processing break; } + mState = STATE_HAVE_RESPONSE; context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes; @@ -370,7 +389,11 @@ LLIOPipe::EStatus LLURLRequest::process_impl( link.mChannels = LLBufferArray::makeChannelConsumer( channels); chain.push_back(link); - pump->respond(chain, buffer, context); + static LLFastTimer::DeclareTimer FTM_PROCESS_URL_PUMP_RESPOND("Pump Respond"); + { + LLFastTimer t(FTM_PROCESS_URL_PUMP_RESPOND); + pump->respond(chain, buffer, context); + } mCompletionCallback = NULL; } break; @@ -422,8 +445,11 @@ void LLURLRequest::initialize() mResponseTransferedBytes = 0; } +static LLFastTimer::DeclareTimer FTM_URL_REQUEST_CONFIGURE("URL Configure"); bool LLURLRequest::configure() { + LLFastTimer t(FTM_URL_REQUEST_CONFIGURE); + LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); bool rv = false; S32 bytes = mDetail->mResponseBuffer->countAfter( @@ -624,6 +650,7 @@ static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user) return header_len; } +static LLFastTimer::DeclareTimer FTM_PROCESS_URL_EXTRACTOR("URL Extractor"); /** * LLContextURLExtractor */ @@ -635,6 +662,7 @@ LLIOPipe::EStatus LLContextURLExtractor::process_impl( LLSD& context, LLPumpIO* pump) { + LLFastTimer t(FTM_PROCESS_URL_EXTRACTOR); PUMP_DEBUG; LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); // The destination host is in the context. @@ -713,6 +741,7 @@ void LLURLRequestComplete::responseStatus(LLIOPipe::EStatus status) mRequestStatus = status; } +static LLFastTimer::DeclareTimer FTM_PROCESS_URL_COMPLETE("URL Complete"); // virtual LLIOPipe::EStatus LLURLRequestComplete::process_impl( const LLChannelDescriptors& channels, @@ -721,6 +750,7 @@ LLIOPipe::EStatus LLURLRequestComplete::process_impl( LLSD& context, LLPumpIO* pump) { + LLFastTimer t(FTM_PROCESS_URL_COMPLETE); PUMP_DEBUG; complete(channels, buffer); return STATUS_OK; -- cgit v1.2.3 From 7b6afd1eba69a61fae87e3f1e7b03d03ee4ea15e Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 21 Jul 2011 23:33:23 -0500 Subject: SH-2031 Followup to curl threading work -- don't start and stop the thread on every request, use a signal (cuts time spent in Pump IO down from 1-2 ms to 0.1ms) --- indra/llmessage/llcurl.cpp | 45 ++++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 13 deletions(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 453ffa9db9..2bb36f494c 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -611,6 +611,9 @@ public: S32 mPerformState; + LLCondition* mSignal; + bool mQuitting; + private: void easyFree(Easy*); @@ -630,6 +633,9 @@ LLCurl::Multi::Multi() mErrorCount(0), mPerformState(PERFORM_STATE_READY) { + mQuitting = false; + mSignal = new LLCondition(NULL); + mCurlMultiHandle = curl_multi_init(); if (!mCurlMultiHandle) { @@ -644,6 +650,10 @@ 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) @@ -674,27 +684,31 @@ void LLCurl::Multi::perform() if (mPerformState == PERFORM_STATE_READY) { mPerformState = PERFORM_STATE_PERFORMING; - start(); + mSignal->signal(); } } 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(); + S32 q = 0; + for (S32 call_count = 0; + call_count < MULTI_PERFORM_CALL_REPEAT; + call_count += 1) { - 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; + mPerformState = PERFORM_STATE_COMPLETED; } - mQueued = q; - mPerformState = PERFORM_STATE_COMPLETED; } S32 LLCurl::Multi::process() @@ -823,6 +837,7 @@ void LLCurlRequest::addMulti() { llassert_always(mThreadID == LLThread::currentID()); LLCurl::Multi* multi = new LLCurl::Multi(); + multi->start(); mMultiSet.insert(multi); mActiveMulti = multi; mActiveRequestCount = 0; @@ -952,9 +967,10 @@ 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); } @@ -988,6 +1004,7 @@ LLCurlEasyRequest::LLCurlEasyRequest() mResultReturned(false) { mMulti = new LLCurl::Multi(); + mMulti->start(); mEasy = mMulti->allocEasy(); if (mEasy) { @@ -998,8 +1015,10 @@ LLCurlEasyRequest::LLCurlEasyRequest() LLCurlEasyRequest::~LLCurlEasyRequest() { + mMulti->mQuitting = true; while (!mMulti->isStopped()) { + mMulti->mSignal->signal(); apr_sleep(1000); } delete mMulti; -- cgit v1.2.3 From e4a8ef4ce2572db98d08233c58e23d3ec75f30d7 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 22 Jul 2011 02:33:55 -0500 Subject: SH-2031 Cleanup from threaded curl implementation (remove errors/loops on shutdown). --- indra/llmessage/llcurl.cpp | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 2bb36f494c..1e735c4bbd 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -693,21 +693,25 @@ void LLCurl::Multi::run() while (!mQuitting) { mSignal->wait(); - S32 q = 0; - for (S32 call_count = 0; - call_count < MULTI_PERFORM_CALL_REPEAT; - call_count += 1) + + if (!mQuitting) { - CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q); - if (CURLM_CALL_MULTI_PERFORM != code || q == 0) + S32 q = 0; + for (S32 call_count = 0; + call_count < MULTI_PERFORM_CALL_REPEAT; + call_count += 1) { - 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; + mPerformState = PERFORM_STATE_COMPLETED; } - mQueued = q; - mPerformState = PERFORM_STATE_COMPLETED; } } @@ -830,6 +834,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()); } -- cgit v1.2.3 From 26a9a6929c23eabfef0a53355a392fef0ad26b83 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 22 Jul 2011 16:22:51 -0500 Subject: SH-2031 Fix for sometimes deadlocking a curl thread. --- indra/llmessage/llcurl.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 1e735c4bbd..0735842dcd 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -683,7 +683,6 @@ void LLCurl::Multi::perform() { if (mPerformState == PERFORM_STATE_READY) { - mPerformState = PERFORM_STATE_PERFORMING; mSignal->signal(); } } @@ -693,7 +692,7 @@ void LLCurl::Multi::run() while (!mQuitting) { mSignal->wait(); - + mPerformState = PERFORM_STATE_PERFORMING; if (!mQuitting) { S32 q = 0; -- cgit v1.2.3 From cd923af21f4fa6e251dea47ffb53ace934a382d1 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 28 Jul 2011 00:26:30 -0500 Subject: SH-2183 Fix for multi-threaded curl not playing nice with mesh upload. --- indra/llmessage/llcurl.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indra/llmessage') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 9484f572f6..b7208f3e19 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -1006,6 +1006,10 @@ S32 LLCurlRequest::getQueued() curlmulti_set_t::iterator curiter = iter++; LLCurl::Multi* multi = *curiter; queued += multi->mQueued; + if (multi->mPerformState != LLCurl::Multi::PERFORM_STATE_READY) + { + ++queued; + } } return queued; } -- cgit v1.2.3 From 3a82169e2e985f1275426eab73683d973dccca29 Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine Date: Mon, 1 Aug 2011 21:33:11 +0300 Subject: STORM-1186 FIXED Removed the "no mCurrentRMessageTemplate" warning message. The mCurrentRMessageTemplate member seems to only be non-NULL for a short while after an incoming message was validated and parsed, thus there is no guarantee that we can obtain name of the last received message at any given time. So if we can't we'll simply return an empty string without spamming the log with warnings. --- indra/llmessage/lltemplatemessagereader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp index f470e1b2a5..ab91f74abe 100644 --- a/indra/llmessage/lltemplatemessagereader.cpp +++ b/indra/llmessage/lltemplatemessagereader.cpp @@ -795,7 +795,7 @@ const char* LLTemplateMessageReader::getMessageName() const { if (!mCurrentRMessageTemplate) { - llwarns << "no mCurrentRMessageTemplate" << llendl; + // no message currently being read return ""; } return mCurrentRMessageTemplate->mName; -- cgit v1.2.3 From fbd5bd7adc205acecc49c7e9887efa3bca6552d0 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 1 Aug 2011 17:50:43 -0500 Subject: SH-2183 Add a debug setting to control whether or not to use multiple threads in LLCurl --- indra/llmessage/llcurl.cpp | 101 +++++++++++++++++++++++++++++++-------------- indra/llmessage/llcurl.h | 4 +- 2 files changed, 74 insertions(+), 31 deletions(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index b7208f3e19..ece539bb48 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -26,6 +26,7 @@ * $/LicenseInfo$ */ + #if LL_WINDOWS #define SAFE_SSL 1 #elif LL_DARWIN @@ -84,6 +85,8 @@ S32 gCurlMultiCount = 0; std::vector LLCurl::sSSLMutex; std::string LLCurl::sCAPath; std::string LLCurl::sCAFile; +bool LLCurl::sMultiThreaded = false; + void check_curl_code(CURLcode code) { @@ -601,6 +604,7 @@ public: S32 process(); void perform(); + void doPerform(); virtual void run(); @@ -634,7 +638,14 @@ LLCurl::Multi::Multi() mPerformState(PERFORM_STATE_READY) { mQuitting = false; - mSignal = new LLCondition(NULL); + if (LLCurl::sMultiThreaded) + { + mSignal = new LLCondition(NULL); + } + else + { + mSignal = NULL; + } mCurlMultiHandle = curl_multi_init(); if (!mCurlMultiHandle) @@ -681,37 +692,51 @@ CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue) void LLCurl::Multi::perform() { - if (mPerformState == PERFORM_STATE_READY) + if (LLCurl::sMultiThreaded) + { + if (mPerformState == PERFORM_STATE_READY) + { + mSignal->signal(); + } + } + else { - mSignal->signal(); + doPerform(); } } void LLCurl::Multi::run() { + llassert(LLCurl::sMultiThreaded); + while (!mQuitting) { mSignal->wait(); mPerformState = PERFORM_STATE_PERFORMING; if (!mQuitting) { - S32 q = 0; - for (S32 call_count = 0; - call_count < MULTI_PERFORM_CALL_REPEAT; - call_count += 1) - { - CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q); - if (CURLM_CALL_MULTI_PERFORM != code || q == 0) - { - check_curl_multi_code(code); - break; - } - - } - mQueued = q; - mPerformState = PERFORM_STATE_COMPLETED; + doPerform(); + } + } +} + +void LLCurl::Multi::doPerform() +{ + S32 q = 0; + for (S32 call_count = 0; + call_count < MULTI_PERFORM_CALL_REPEAT; + call_count += 1) + { + CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q); + if (CURLM_CALL_MULTI_PERFORM != code || q == 0) + { + check_curl_multi_code(code); + break; } + } + mQueued = q; + mPerformState = PERFORM_STATE_COMPLETED; } S32 LLCurl::Multi::process() @@ -839,10 +864,13 @@ LLCurlRequest::~LLCurlRequest() { LLCurl::Multi* multi = *iter; multi->mQuitting = true; - while (!multi->isStopped()) + if (LLCurl::sMultiThreaded) { - multi->mSignal->signal(); - apr_sleep(1000); + while (!multi->isStopped()) + { + multi->mSignal->signal(); + apr_sleep(1000); + } } } for_each(mMultiSet.begin(), mMultiSet.end(), DeletePointer()); @@ -852,7 +880,10 @@ void LLCurlRequest::addMulti() { llassert_always(mThreadID == LLThread::currentID()); LLCurl::Multi* multi = new LLCurl::Multi(); - multi->start(); + if (LLCurl::sMultiThreaded) + { + multi->start(); + } mMultiSet.insert(multi); mActiveMulti = multi; mActiveRequestCount = 0; @@ -983,10 +1014,13 @@ S32 LLCurlRequest::process() { mMultiSet.erase(curiter); multi->mQuitting = true; - while (!multi->isStopped()) + if (LLCurl::sMultiThreaded) { - multi->mSignal->signal(); - apr_sleep(1000); + while (!multi->isStopped()) + { + multi->mSignal->signal(); + apr_sleep(1000); + } } delete multi; @@ -1023,7 +1057,10 @@ LLCurlEasyRequest::LLCurlEasyRequest() mResultReturned(false) { mMulti = new LLCurl::Multi(); - mMulti->start(); + if (LLCurl::sMultiThreaded) + { + mMulti->start(); + } mEasy = mMulti->allocEasy(); if (mEasy) { @@ -1035,10 +1072,13 @@ LLCurlEasyRequest::LLCurlEasyRequest() LLCurlEasyRequest::~LLCurlEasyRequest() { mMulti->mQuitting = true; - while (!mMulti->isStopped()) + if (LLCurl::sMultiThreaded) { - mMulti->mSignal->signal(); - apr_sleep(1000); + while (!mMulti->isStopped()) + { + mMulti->mSignal->signal(); + apr_sleep(1000); + } } delete mMulti; } @@ -1234,8 +1274,9 @@ unsigned long LLCurl::ssl_thread_id(void) } #endif -void LLCurl::initClass() +void LLCurl::initClass(bool multi_threaded) { + sMultiThreaded = multi_threaded; // Do not change this "unless you are familiar with and mean to control // internal operations of libcurl" // - http://curl.haxx.se/libcurl/c/curl_global_init.html diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 56d086c30a..b2c7b36a76 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -55,6 +55,8 @@ public: class Easy; class Multi; + static bool sMultiThreaded; + struct TransferInfo { TransferInfo() : mSizeDownload(0.0), mTotalTime(0.0), mSpeedDownload(0.0) {} @@ -159,7 +161,7 @@ public: /** * @ brief Initialize LLCurl class */ - static void initClass(); + static void initClass(bool multi_threaded = false); /** * @ brief Cleanup LLCurl class -- cgit v1.2.3 From aa0e35142a35d293acc439e3194260bb4468e728 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 2 Aug 2011 12:23:50 -0500 Subject: SH-2183 Only apply multi-threaded curl on the main thread. --- indra/llmessage/llcurl.cpp | 3 ++- indra/llmessage/llcurl.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index ece539bb48..d48991e5f7 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -85,7 +85,8 @@ S32 gCurlMultiCount = 0; std::vector LLCurl::sSSLMutex; std::string LLCurl::sCAPath; std::string LLCurl::sCAFile; -bool LLCurl::sMultiThreaded = false; + +bool ll_thread_local LLCurl::sMultiThreaded = false; void check_curl_code(CURLcode code) diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index b2c7b36a76..52810bac73 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -41,6 +41,7 @@ #include "llbuffer.h" #include "lliopipe.h" #include "llsd.h" +#include "llthread.h" class LLMutex; @@ -55,7 +56,7 @@ public: class Easy; class Multi; - static bool sMultiThreaded; + static bool ll_thread_local sMultiThreaded; struct TransferInfo { -- cgit v1.2.3 From 9883c33993f7a548c876b43494ffd5835473a211 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 2 Aug 2011 12:47:35 -0500 Subject: SH-2183 Thread local storage initialization is unreliable. --- indra/llmessage/llcurl.cpp | 25 +++++++++++++++---------- indra/llmessage/llcurl.h | 2 +- 2 files changed, 16 insertions(+), 11 deletions(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index d48991e5f7..1a86a69a04 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -75,6 +75,7 @@ static const S32 MULTI_PERFORM_CALL_REPEAT = 5; static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds static const S32 MAX_ACTIVE_REQUEST_COUNT = 100; +static // DEBUG // S32 gCurlEasyCount = 0; S32 gCurlMultiCount = 0; @@ -86,8 +87,8 @@ std::vector LLCurl::sSSLMutex; std::string LLCurl::sCAPath; std::string LLCurl::sCAFile; -bool ll_thread_local LLCurl::sMultiThreaded = false; - +bool LLCurl::sMultiThreaded = false; +static U32 sMainThreadID = 0; void check_curl_code(CURLcode code) { @@ -618,6 +619,7 @@ public: LLCondition* mSignal; bool mQuitting; + bool mThreaded; private: void easyFree(Easy*); @@ -639,7 +641,9 @@ LLCurl::Multi::Multi() mPerformState(PERFORM_STATE_READY) { mQuitting = false; - if (LLCurl::sMultiThreaded) + + mThreaded = LLCurl::sMultiThreaded && LLThread::currentID() == sMainThreadID; + if (mThreaded) { mSignal = new LLCondition(NULL); } @@ -693,7 +697,7 @@ CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue) void LLCurl::Multi::perform() { - if (LLCurl::sMultiThreaded) + if (mThreaded) { if (mPerformState == PERFORM_STATE_READY) { @@ -708,7 +712,7 @@ void LLCurl::Multi::perform() void LLCurl::Multi::run() { - llassert(LLCurl::sMultiThreaded); + llassert(mThreaded); while (!mQuitting) { @@ -865,7 +869,7 @@ LLCurlRequest::~LLCurlRequest() { LLCurl::Multi* multi = *iter; multi->mQuitting = true; - if (LLCurl::sMultiThreaded) + if (multi->mThreaded) { while (!multi->isStopped()) { @@ -881,7 +885,7 @@ void LLCurlRequest::addMulti() { llassert_always(mThreadID == LLThread::currentID()); LLCurl::Multi* multi = new LLCurl::Multi(); - if (LLCurl::sMultiThreaded) + if (multi->mThreaded) { multi->start(); } @@ -1015,7 +1019,7 @@ S32 LLCurlRequest::process() { mMultiSet.erase(curiter); multi->mQuitting = true; - if (LLCurl::sMultiThreaded) + if (multi->mThreaded) { while (!multi->isStopped()) { @@ -1058,7 +1062,7 @@ LLCurlEasyRequest::LLCurlEasyRequest() mResultReturned(false) { mMulti = new LLCurl::Multi(); - if (LLCurl::sMultiThreaded) + if (mMulti->mThreaded) { mMulti->start(); } @@ -1073,7 +1077,7 @@ LLCurlEasyRequest::LLCurlEasyRequest() LLCurlEasyRequest::~LLCurlEasyRequest() { mMulti->mQuitting = true; - if (LLCurl::sMultiThreaded) + if (mMulti->mThreaded) { while (!mMulti->isStopped()) { @@ -1277,6 +1281,7 @@ 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" diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 52810bac73..f7518c8e5c 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -56,7 +56,7 @@ public: class Easy; class Multi; - static bool ll_thread_local sMultiThreaded; + static bool sMultiThreaded; struct TransferInfo { -- cgit v1.2.3