From 57bd7c8e6e2f9b5e2668549afabf1c8468cd61a9 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Thu, 16 Feb 2012 12:07:02 +0100 Subject: [PATCH] Added timeout check for non-firing HTTP GET callbacks with fallback to simulator fetch --- indra/newview/lltexturefetch.cpp | 66 ++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 195e28bc9e..1149e38b06 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -287,6 +287,11 @@ private: U8 mImageCodec; LLViewerAssetStats::duration_t mMetricsStartTime; + + // CURL timeout check + LLFrameTimer mHttpCallbackTimer; + S32 mHttpCallbackTimeoutCount; + // CURL timeout check }; ////////////////////////////////////////////////////////////////////////////// @@ -683,7 +688,11 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mLastPacket(-1), mTotalPackets(0), mImageCodec(IMG_CODEC_INVALID), - mMetricsStartTime(0) + // CURL timeout check + //mMetricsStartTime(0) + mMetricsStartTime(0), + mHttpCallbackTimeoutCount(0) + // CURL timeout check { mCanUseNET = mUrl.empty() ; @@ -1217,6 +1226,8 @@ bool LLTextureFetchWorker::doWork(S32 param) headers.push_back("Accept: image/x-j2c"); res = mFetcher->mCurlGetRequest->getByteRange(mUrl, headers, offset, mRequestedSize, new HTTPGetResponder(mFetcher, mID, LLTimer::getTotalTime(), mRequestedSize, offset, true)); + + mHttpCallbackTimer.reset(); // CURL timeout check } if (!res) { @@ -1377,8 +1388,57 @@ bool LLTextureFetchWorker::doWork(S32 param) } else { - setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); - return false; + // CURL timeout check: In case CURL does not + // fire the callback method, the fetch worker + // thread would be stuck in the queue. + //setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); + //return false; + const F32 HTTP_CALLBACK_TIMEOUT = 30.f; + const S32 MAX_HTTP_CALLBACK_TIMEOUTS = 3; + if (mHttpCallbackTimer.getElapsedTimeF32() > HTTP_CALLBACK_TIMEOUT) + { + mFetcher->removeFromHTTPQueue(mID); + mHttpCallbackTimeoutCount++; + if (mHttpCallbackTimeoutCount < MAX_HTTP_CALLBACK_TIMEOUTS) + { + // Maximum retries not reached. Try again via HTTP. + llwarns << "HTTP callback timeout for " << mID + << " (Attempt " << mHttpCallbackTimeoutCount + << "/" << MAX_HTTP_CALLBACK_TIMEOUTS << "). Retrying..." << llendl; + mState = SEND_HTTP_REQ; + return false; + } + else + { + mHttpCallbackTimer.stop(); + + // Maximum retries reached. Try via simulator + // fetch if possible. Abort if not. + if (mCanUseNET) + { + llwarns << "HTTP callback timeout limit reached for " << mID + << ". Retrying via simulator fetch..." << llendl; + mState = INIT; + mCanUseHTTP = false; + setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); + return false; + } + else + { + llwarns << "HTTP callback timeout limit reached for " << mID + << ". No simulator fetch available. Aborting!" << llendl; + mState = DONE; + return true; + } + } + } + else + { + // Timeout not reached. Continue waiting... + setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); + return false; + } + // CURL timeout check } }