From 57d5744f2c064ccb7bf8dd3dca2a24f6755297ac Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Fri, 28 Jul 2017 14:07:25 -0700 Subject: MAINT-7634: Move StatsAccumulator into llcommon, collect data sent and error codes from core. --- indra/llcorehttp/_httpoprequest.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indra/llcorehttp/_httpoprequest.cpp') diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index 07cc0e4625..f35f9848ff 100644 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -47,6 +47,8 @@ #include "llhttpconstants.h" #include "llproxy.h" +#include "httpstats.h" + // *DEBUG: "[curl:bugs] #1420" problem and testing. // // A pipelining problem, https://sourceforge.net/p/curl/bugs/1420/, @@ -805,6 +807,7 @@ size_t HttpOpRequest::writeCallback(void * data, size_t size, size_t nmemb, void } const size_t req_size(size * nmemb); const size_t write_size(op->mReplyBody->append(static_cast(data), req_size)); + HTTPStats::instance().recordDataDown(write_size); return write_size; } @@ -833,7 +836,8 @@ size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void const size_t do_size((std::min)(req_size, body_size - op->mCurlBodyPos)); const size_t read_size(op->mReqBody->read(op->mCurlBodyPos, static_cast(data), do_size)); - op->mCurlBodyPos += read_size; + HTTPStats::instance().recordDataUp(read_size); + op->mCurlBodyPos += read_size; return read_size; } -- cgit v1.3 From 1038633526330cf931ba097dbafdd270b5bb56e3 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Tue, 8 Aug 2017 09:04:32 -0700 Subject: MAINT-7634: Logging and instrumentation canges to narrow down viewer crashes. --- indra/llcommon/llthread.cpp | 465 ++++++++++++++++++++---------------- indra/llcommon/llthread.h | 190 +++++++-------- indra/llcorehttp/_httpoprequest.cpp | 19 ++ indra/llcorehttp/_httppolicy.cpp | 2 +- indra/llcorehttp/httprequest.cpp | 10 +- indra/llcorehttp/httprequest.h | 13 - indra/llcorehttp/httpresponse.h | 10 + indra/llcorehttp/httpstats.cpp | 34 ++- indra/llcorehttp/httpstats.h | 4 + indra/llmessage/llcorehttputil.cpp | 21 +- 10 files changed, 426 insertions(+), 342 deletions(-) (limited to 'indra/llcorehttp/_httpoprequest.cpp') diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 52255bfaeb..b96b2ce4bc 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -34,6 +34,7 @@ #include "lltimer.h" #include "lltrace.h" #include "lltracethreadrecorder.h" +#include "llexception.h" #if LL_LINUX || LL_SOLARIS #include @@ -46,28 +47,28 @@ const DWORD MS_VC_EXCEPTION=0x406D1388; #pragma pack(push,8) typedef struct tagTHREADNAME_INFO { - DWORD dwType; // Must be 0x1000. - LPCSTR szName; // Pointer to name (in user addr space). - DWORD dwThreadID; // Thread ID (-1=caller thread). - DWORD dwFlags; // Reserved for future use, must be zero. + DWORD dwType; // Must be 0x1000. + LPCSTR szName; // Pointer to name (in user addr space). + DWORD dwThreadID; // Thread ID (-1=caller thread). + DWORD dwFlags; // Reserved for future use, must be zero. } THREADNAME_INFO; #pragma pack(pop) void set_thread_name( DWORD dwThreadID, const char* threadName) { - THREADNAME_INFO info; - info.dwType = 0x1000; - info.szName = threadName; - info.dwThreadID = dwThreadID; - info.dwFlags = 0; - - __try - { - ::RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (ULONG_PTR*)&info ); - } - __except(EXCEPTION_CONTINUE_EXECUTION) - { - } + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = threadName; + info.dwThreadID = dwThreadID; + info.dwFlags = 0; + + __try + { + ::RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (ULONG_PTR*)&info ); + } + __except(EXCEPTION_CONTINUE_EXECUTION) + { + } } #endif @@ -99,17 +100,17 @@ U32 LLThread::sIDIter = 0; LL_COMMON_API void assert_main_thread() { - static U32 s_thread_id = LLThread::currentID(); - if (LLThread::currentID() != s_thread_id) - { - LL_WARNS() << "Illegal execution from thread id " << (S32) LLThread::currentID() - << " outside main thread " << (S32) s_thread_id << LL_ENDL; - } + static U32 s_thread_id = LLThread::currentID(); + if (LLThread::currentID() != s_thread_id) + { + LL_WARNS() << "Illegal execution from thread id " << (S32) LLThread::currentID() + << " outside main thread " << (S32) s_thread_id << LL_ENDL; + } } void LLThread::registerThreadID() { - sThreadID = ++sIDIter; + sThreadID = ++sIDIter; } // @@ -117,157 +118,203 @@ void LLThread::registerThreadID() // void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap) { - LLThread *threadp = (LLThread *)datap; + LLThread *threadp = (LLThread *)datap; #ifdef LL_WINDOWS - set_thread_name(-1, threadp->mName.c_str()); + set_thread_name(-1, threadp->mName.c_str()); #endif - // for now, hard code all LLThreads to report to single master thread recorder, which is known to be running on main thread - threadp->mRecorder = new LLTrace::ThreadRecorder(*LLTrace::get_master_thread_recorder()); - - sThreadID = threadp->mID; - - // Run the user supplied function - threadp->run(); - - //LL_INFOS() << "LLThread::staticRun() Exiting: " << threadp->mName << LL_ENDL; - - delete threadp->mRecorder; - threadp->mRecorder = NULL; - - // We're done with the run function, this thread is done executing now. - //NB: we are using this flag to sync across threads...we really need memory barriers here - threadp->mStatus = STOPPED; - - return NULL; + // for now, hard code all LLThreads to report to single master thread recorder, which is known to be running on main thread + threadp->mRecorder = new LLTrace::ThreadRecorder(*LLTrace::get_master_thread_recorder()); + + sThreadID = threadp->mID; + + try + { + // Run the user supplied function + do + { + try + { + threadp->run(); + } + catch (const LLContinueError &e) + { + LL_WARNS("THREAD") << "ContinueException on thread '" << threadp->mName << + "' reentering run(). Error what is: '" << e.what() << "'" << LL_ENDL; + //output possible call stacks to log file. + LLError::LLCallStacks::print(); + + LOG_UNHANDLED_EXCEPTION("LLThread"); + continue; + } + break; + + } while (true); + + //LL_INFOS() << "LLThread::staticRun() Exiting: " << threadp->mName << LL_ENDL; + + // We're done with the run function, this thread is done executing now. + //NB: we are using this flag to sync across threads...we really need memory barriers here + threadp->mStatus = STOPPED; + } + catch (std::bad_alloc) + { + threadp->mStatus = CRASHED; + LLMemory::logMemoryInfo(TRUE); + + //output possible call stacks to log file. + LLError::LLCallStacks::print(); + + LL_ERRS("THREAD") << "Bad memory allocation in LLThread::staticRun() named '" << threadp->mName << "'!" << LL_ENDL; + } + catch (...) + { + threadp->mStatus = CRASHED; + CRASH_ON_UNHANDLED_EXCEPTION("LLThread"); + } + + delete threadp->mRecorder; + threadp->mRecorder = NULL; + + return NULL; } LLThread::LLThread(const std::string& name, apr_pool_t *poolp) : - mPaused(FALSE), - mName(name), - mAPRThreadp(NULL), - mStatus(STOPPED), - mRecorder(NULL) + mPaused(FALSE), + mName(name), + mAPRThreadp(NULL), + mStatus(STOPPED), + mRecorder(NULL) { - mID = ++sIDIter; - - // Thread creation probably CAN be paranoid about APR being initialized, if necessary - if (poolp) - { - mIsLocalPool = FALSE; - mAPRPoolp = poolp; - } - else - { - mIsLocalPool = TRUE; - apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread - } - mRunCondition = new LLCondition(mAPRPoolp); - mDataLock = new LLMutex(mAPRPoolp); - mLocalAPRFilePoolp = NULL ; + mID = ++sIDIter; + + // Thread creation probably CAN be paranoid about APR being initialized, if necessary + if (poolp) + { + mIsLocalPool = FALSE; + mAPRPoolp = poolp; + } + else + { + mIsLocalPool = TRUE; + apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread + } + mRunCondition = new LLCondition(mAPRPoolp); + mDataLock = new LLMutex(mAPRPoolp); + mLocalAPRFilePoolp = NULL ; } LLThread::~LLThread() { - shutdown(); - - if(mLocalAPRFilePoolp) - { - delete mLocalAPRFilePoolp ; - mLocalAPRFilePoolp = NULL ; - } + shutdown(); + + if (isCrashed()) + { + LL_WARNS("THREAD") << "Destroying crashed thread named '" << mName << "'" << LL_ENDL; + } + + if(mLocalAPRFilePoolp) + { + delete mLocalAPRFilePoolp ; + mLocalAPRFilePoolp = NULL ; + } } void LLThread::shutdown() { - // Warning! If you somehow call the thread destructor from itself, - // the thread will die in an unclean fashion! - if (mAPRThreadp) - { - if (!isStopped()) - { - // The thread isn't already stopped - // First, set the flag that indicates that we're ready to die - setQuitting(); - - //LL_INFOS() << "LLThread::~LLThread() Killing thread " << mName << " Status: " << mStatus << LL_ENDL; - // Now wait a bit for the thread to exit - // It's unclear whether I should even bother doing this - this destructor - // should never get called unless we're already stopped, really... - S32 counter = 0; - const S32 MAX_WAIT = 600; - while (counter < MAX_WAIT) - { - if (isStopped()) - { - break; - } - // Sleep for a tenth of a second - ms_sleep(100); - yield(); - counter++; - } - } - - if (!isStopped()) - { - // This thread just wouldn't stop, even though we gave it time - //LL_WARNS() << "LLThread::~LLThread() exiting thread before clean exit!" << LL_ENDL; - // Put a stake in its heart. - delete mRecorder; - - apr_thread_exit(mAPRThreadp, -1); - return; - } - mAPRThreadp = NULL; - } - - delete mRunCondition; - mRunCondition = NULL; - - delete mDataLock; - mDataLock = NULL; - - if (mIsLocalPool && mAPRPoolp) - { - apr_pool_destroy(mAPRPoolp); - mAPRPoolp = 0; - } - - if (mRecorder) - { - // missed chance to properly shut down recorder (needs to be done in thread context) - // probably due to abnormal thread termination - // so just leak it and remove it from parent - LLTrace::get_master_thread_recorder()->removeChildRecorder(mRecorder); - } + if (isCrashed()) + { + LL_WARNS("THREAD") << "Shutting down crashed thread named '" << mName << "'" << LL_ENDL; + } + + // Warning! If you somehow call the thread destructor from itself, + // the thread will die in an unclean fashion! + if (mAPRThreadp) + { + if (!isStopped()) + { + // The thread isn't already stopped + // First, set the flag that indicates that we're ready to die + setQuitting(); + + //LL_INFOS() << "LLThread::~LLThread() Killing thread " << mName << " Status: " << mStatus << LL_ENDL; + // Now wait a bit for the thread to exit + // It's unclear whether I should even bother doing this - this destructor + // should never get called unless we're already stopped, really... + S32 counter = 0; + const S32 MAX_WAIT = 600; + while (counter < MAX_WAIT) + { + if (isStopped()) + { + break; + } + // Sleep for a tenth of a second + ms_sleep(100); + yield(); + counter++; + } + } + + if (!isStopped()) + { + // This thread just wouldn't stop, even though we gave it time + //LL_WARNS() << "LLThread::~LLThread() exiting thread before clean exit!" << LL_ENDL; + // Put a stake in its heart. + delete mRecorder; + + apr_thread_exit(mAPRThreadp, -1); + return; + } + mAPRThreadp = NULL; + } + + delete mRunCondition; + mRunCondition = NULL; + + delete mDataLock; + mDataLock = NULL; + + if (mIsLocalPool && mAPRPoolp) + { + apr_pool_destroy(mAPRPoolp); + mAPRPoolp = 0; + } + + if (mRecorder) + { + // missed chance to properly shut down recorder (needs to be done in thread context) + // probably due to abnormal thread termination + // so just leak it and remove it from parent + LLTrace::get_master_thread_recorder()->removeChildRecorder(mRecorder); + } } void LLThread::start() { - llassert(isStopped()); - - // Set thread state to running - mStatus = RUNNING; - - apr_status_t status = - apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp); - - if(status == APR_SUCCESS) - { - // We won't bother joining - apr_thread_detach(mAPRThreadp); - } - else - { - mStatus = STOPPED; - LL_WARNS() << "failed to start thread " << mName << LL_ENDL; - ll_apr_warn_status(status); - } + llassert(isStopped()); + + // Set thread state to running + mStatus = RUNNING; + + apr_status_t status = + apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp); + + if(status == APR_SUCCESS) + { + // We won't bother joining + apr_thread_detach(mAPRThreadp); + } + else + { + mStatus = STOPPED; + LL_WARNS() << "failed to start thread " << mName << LL_ENDL; + ll_apr_warn_status(status); + } } @@ -278,28 +325,28 @@ void LLThread::start() // The thread will pause when (and if) it calls checkPause() void LLThread::pause() { - if (!mPaused) - { - // this will cause the thread to stop execution as soon as checkPause() is called - mPaused = 1; // Does not need to be atomic since this is only set/unset from the main thread - } + if (!mPaused) + { + // this will cause the thread to stop execution as soon as checkPause() is called + mPaused = 1; // Does not need to be atomic since this is only set/unset from the main thread + } } void LLThread::unpause() { - if (mPaused) - { - mPaused = 0; - } + if (mPaused) + { + mPaused = 0; + } - wake(); // wake up the thread if necessary + wake(); // wake up the thread if necessary } // virtual predicate function -- returns true if the thread should wake up, false if it should sleep. bool LLThread::runCondition(void) { - // by default, always run. Handling of pause/unpause is done regardless of this function's result. - return true; + // by default, always run. Handling of pause/unpause is done regardless of this function's result. + return true; } //============================================================================ @@ -307,65 +354,65 @@ bool LLThread::runCondition(void) // Stop thread execution if requested until unpaused. void LLThread::checkPause() { - mDataLock->lock(); - - // This is in a while loop because the pthread API allows for spurious wakeups. - while(shouldSleep()) - { - mDataLock->unlock(); - mRunCondition->wait(); // unlocks mRunCondition - mDataLock->lock(); - // mRunCondition is locked when the thread wakes up - } - - mDataLock->unlock(); + mDataLock->lock(); + + // This is in a while loop because the pthread API allows for spurious wakeups. + while(shouldSleep()) + { + mDataLock->unlock(); + mRunCondition->wait(); // unlocks mRunCondition + mDataLock->lock(); + // mRunCondition is locked when the thread wakes up + } + + mDataLock->unlock(); } //============================================================================ void LLThread::setQuitting() { - mDataLock->lock(); - if (mStatus == RUNNING) - { - mStatus = QUITTING; - } - mDataLock->unlock(); - wake(); + mDataLock->lock(); + if (mStatus == RUNNING) + { + mStatus = QUITTING; + } + mDataLock->unlock(); + wake(); } // static U32 LLThread::currentID() { - return sThreadID; + return sThreadID; } // static void LLThread::yield() { #if LL_LINUX || LL_SOLARIS - sched_yield(); // annoyingly, apr_thread_yield is a noop on linux... + sched_yield(); // annoyingly, apr_thread_yield is a noop on linux... #else - apr_thread_yield(); + apr_thread_yield(); #endif } void LLThread::wake() { - mDataLock->lock(); - if(!shouldSleep()) - { - mRunCondition->signal(); - } - mDataLock->unlock(); + mDataLock->lock(); + if(!shouldSleep()) + { + mRunCondition->signal(); + } + mDataLock->unlock(); } void LLThread::wakeLocked() { - if(!shouldSleep()) - { - mRunCondition->signal(); - } + if(!shouldSleep()) + { + mRunCondition->signal(); + } } //============================================================================ @@ -378,38 +425,38 @@ LLMutex* LLThreadSafeRefCount::sMutex = 0; //static void LLThreadSafeRefCount::initThreadSafeRefCount() { - if (!sMutex) - { - sMutex = new LLMutex(0); - } + if (!sMutex) + { + sMutex = new LLMutex(0); + } } //static void LLThreadSafeRefCount::cleanupThreadSafeRefCount() { - delete sMutex; - sMutex = NULL; + delete sMutex; + sMutex = NULL; } - + //---------------------------------------------------------------------------- LLThreadSafeRefCount::LLThreadSafeRefCount() : - mRef(0) + mRef(0) { } LLThreadSafeRefCount::LLThreadSafeRefCount(const LLThreadSafeRefCount& src) { - mRef = 0; + mRef = 0; } LLThreadSafeRefCount::~LLThreadSafeRefCount() { - if (mRef != 0) - { - LL_ERRS() << "deleting non-zero reference" << LL_ENDL; - } + if (mRef != 0) + { + LL_ERRS() << "deleting non-zero reference" << LL_ENDL; + } } //============================================================================ diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index 6f9ec10fd3..dda7fa8ffb 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -38,118 +38,120 @@ LL_COMMON_API void assert_main_thread(); namespace LLTrace { - class ThreadRecorder; + class ThreadRecorder; } class LL_COMMON_API LLThread { private: - friend class LLMutex; - static U32 sIDIter; + friend class LLMutex; + static U32 sIDIter; public: - typedef enum e_thread_status - { - STOPPED = 0, // The thread is not running. Not started, or has exited its run function - RUNNING = 1, // The thread is currently running - QUITTING= 2 // Someone wants this thread to quit - } EThreadStatus; - - LLThread(const std::string& name, apr_pool_t *poolp = NULL); - virtual ~LLThread(); // Warning! You almost NEVER want to destroy a thread unless it's in the STOPPED state. - virtual void shutdown(); // stops the thread - - bool isQuitting() const { return (QUITTING == mStatus); } - bool isStopped() const { return (STOPPED == mStatus); } - - static U32 currentID(); // Return ID of current thread - static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure. - + typedef enum e_thread_status + { + STOPPED = 0, // The thread is not running. Not started, or has exited its run function + RUNNING = 1, // The thread is currently running + QUITTING= 2, // Someone wants this thread to quit + CRASHED = -1 // An uncaught exception was thrown by the thread + } EThreadStatus; + + LLThread(const std::string& name, apr_pool_t *poolp = NULL); + virtual ~LLThread(); // Warning! You almost NEVER want to destroy a thread unless it's in the STOPPED state. + virtual void shutdown(); // stops the thread + + bool isQuitting() const { return (QUITTING == mStatus); } + bool isStopped() const { return (STOPPED == mStatus) || (CRASHED == mStatus); } + bool isCrashed() const { return (CRASHED == mStatus); } + + static U32 currentID(); // Return ID of current thread + static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure. + public: - // PAUSE / RESUME functionality. See source code for important usage notes. - // Called from MAIN THREAD. - void pause(); - void unpause(); - bool isPaused() { return isStopped() || mPaused == TRUE; } - - // Cause the thread to wake up and check its condition - void wake(); - - // Same as above, but to be used when the condition is already locked. - void wakeLocked(); - - // Called from run() (CHILD THREAD). Pause the thread if requested until unpaused. - void checkPause(); - - // this kicks off the apr thread - void start(void); - - apr_pool_t *getAPRPool() { return mAPRPoolp; } - LLVolatileAPRPool* getLocalAPRFilePool() { return mLocalAPRFilePoolp ; } - - U32 getID() const { return mID; } - - // Called by threads *not* created via LLThread to register some - // internal state used by LLMutex. You must call this once early - // in the running thread to prevent collisions with the main thread. - static void registerThreadID(); - + // PAUSE / RESUME functionality. See source code for important usage notes. + // Called from MAIN THREAD. + void pause(); + void unpause(); + bool isPaused() { return isStopped() || mPaused == TRUE; } + + // Cause the thread to wake up and check its condition + void wake(); + + // Same as above, but to be used when the condition is already locked. + void wakeLocked(); + + // Called from run() (CHILD THREAD). Pause the thread if requested until unpaused. + void checkPause(); + + // this kicks off the apr thread + void start(void); + + apr_pool_t *getAPRPool() { return mAPRPoolp; } + LLVolatileAPRPool* getLocalAPRFilePool() { return mLocalAPRFilePoolp ; } + + U32 getID() const { return mID; } + + // Called by threads *not* created via LLThread to register some + // internal state used by LLMutex. You must call this once early + // in the running thread to prevent collisions with the main thread. + static void registerThreadID(); + private: - BOOL mPaused; - - // static function passed to APR thread creation routine - static void *APR_THREAD_FUNC staticRun(struct apr_thread_t *apr_threadp, void *datap); + BOOL mPaused; + + // static function passed to APR thread creation routine + static void *APR_THREAD_FUNC staticRun(struct apr_thread_t *apr_threadp, void *datap); protected: - std::string mName; - class LLCondition* mRunCondition; - LLMutex* mDataLock; - - apr_thread_t *mAPRThreadp; - apr_pool_t *mAPRPoolp; - BOOL mIsLocalPool; - EThreadStatus mStatus; - U32 mID; - LLTrace::ThreadRecorder* mRecorder; - - //a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used. - //Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes. - // otherwise it will cause severe memory leaking!!! --bao - LLVolatileAPRPool *mLocalAPRFilePoolp ; - - void setQuitting(); - - // virtual function overridden by subclass -- this will be called when the thread runs - virtual void run(void) = 0; - - // virtual predicate function -- returns true if the thread should wake up, false if it should sleep. - virtual bool runCondition(void); - - // Lock/Unlock Run Condition -- use around modification of any variable used in runCondition() - inline void lockData(); - inline void unlockData(); - - // This is the predicate that decides whether the thread should sleep. - // It should only be called with mDataLock locked, since the virtual runCondition() function may need to access - // data structures that are thread-unsafe. - bool shouldSleep(void) { return (mStatus == RUNNING) && (isPaused() || (!runCondition())); } - - // To avoid spurious signals (and the associated context switches) when the condition may or may not have changed, you can do the following: - // mDataLock->lock(); - // if(!shouldSleep()) - // mRunCondition->signal(); - // mDataLock->unlock(); + std::string mName; + class LLCondition* mRunCondition; + LLMutex* mDataLock; + + apr_thread_t *mAPRThreadp; + apr_pool_t *mAPRPoolp; + BOOL mIsLocalPool; + EThreadStatus mStatus; + U32 mID; + LLTrace::ThreadRecorder* mRecorder; + + //a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used. + //Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes. + // otherwise it will cause severe memory leaking!!! --bao + LLVolatileAPRPool *mLocalAPRFilePoolp ; + + void setQuitting(); + + // virtual function overridden by subclass -- this will be called when the thread runs + virtual void run(void) = 0; + + // virtual predicate function -- returns true if the thread should wake up, false if it should sleep. + virtual bool runCondition(void); + + // Lock/Unlock Run Condition -- use around modification of any variable used in runCondition() + inline void lockData(); + inline void unlockData(); + + // This is the predicate that decides whether the thread should sleep. + // It should only be called with mDataLock locked, since the virtual runCondition() function may need to access + // data structures that are thread-unsafe. + bool shouldSleep(void) { return (mStatus == RUNNING) && (isPaused() || (!runCondition())); } + + // To avoid spurious signals (and the associated context switches) when the condition may or may not have changed, you can do the following: + // mDataLock->lock(); + // if(!shouldSleep()) + // mRunCondition->signal(); + // mDataLock->unlock(); }; void LLThread::lockData() { - mDataLock->lock(); + mDataLock->lock(); } void LLThread::unlockData() { - mDataLock->unlock(); + mDataLock->unlock(); } @@ -160,9 +162,9 @@ void LLThread::unlockData() class LL_COMMON_API LLResponder : public LLThreadSafeRefCount { protected: - virtual ~LLResponder(); + virtual ~LLResponder(); public: - virtual void completed(bool success) = 0; + virtual void completed(bool success) = 0; }; //============================================================================ diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index f35f9848ff..36955f3797 100644 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -247,6 +247,25 @@ void HttpOpRequest::visitNotifier(HttpRequest * request) response->setHeaders(mReplyHeaders); response->setRequestURL(mReqURL); + std::string method("UNKNOWN"); + + if (mReqMethod == HOR_COPY) + method = "COPY"; + else if (mReqMethod == HOR_DELETE) + method = "DELETE"; + else if (mReqMethod == HOR_GET) + method = "GET"; + else if (mReqMethod == HOR_MOVE) + method = "MOVE"; + else if (mReqMethod == HOR_PATCH) + method = "PATCH"; + else if (mReqMethod == HOR_POST) + method = "POST"; + else if (mReqMethod == HOR_PUT) + method = "PUT"; + + response->setRequestMethod(method); + if (mReplyOffset || mReplyLength) { // Got an explicit offset/length in response diff --git a/indra/llcorehttp/_httppolicy.cpp b/indra/llcorehttp/_httppolicy.cpp index 628a5c79e1..a302db8b46 100644 --- a/indra/llcorehttp/_httppolicy.cpp +++ b/indra/llcorehttp/_httppolicy.cpp @@ -450,7 +450,7 @@ bool HttpPolicy::stageAfterCompletion(const HttpOpRequest::ptr_t &op) op->stageFromActive(mService); - HTTPStats::instance().recordResultCode(op->mStatus.getStatus()); + HTTPStats::instance().recordResultCode(op->mStatus.getType()); return false; // not active } diff --git a/indra/llcorehttp/httprequest.cpp b/indra/llcorehttp/httprequest.cpp index d9662c1232..2687f77217 100644 --- a/indra/llcorehttp/httprequest.cpp +++ b/indra/llcorehttp/httprequest.cpp @@ -52,7 +52,6 @@ namespace LLCore // ==================================== // HttpRequest Implementation // ==================================== -HttpRequest::Statistics HttpRequest::mStatistics; HttpRequest::HttpRequest() @@ -64,11 +63,7 @@ HttpRequest::HttpRequest() mReplyQueue.reset( new HttpReplyQueue() ); - ++mStatistics.mCurrentRequests; - ++mStatistics.mTotalRequests; - - - LL_WARNS("HTTPRequest") << "New HttpRequest created (outstanding: " << mStatistics.mCurrentRequests << " total: " << mStatistics.mTotalRequests << ")" << LL_ENDL; + HTTPStats::instance().recordHTTPRequest(); } @@ -81,9 +76,6 @@ HttpRequest::~HttpRequest() } mReplyQueue.reset(); - --mStatistics.mCurrentRequests; - - LL_WARNS("HTTPRequest") << "HttpRequest destroyed (outstanding: " << mStatistics.mCurrentRequests << " total: " << mStatistics.mTotalRequests << ")" << LL_ENDL; } diff --git a/indra/llcorehttp/httprequest.h b/indra/llcorehttp/httprequest.h index c958132ae2..a418eb6a7a 100644 --- a/indra/llcorehttp/httprequest.h +++ b/indra/llcorehttp/httprequest.h @@ -681,19 +681,6 @@ private: // End Global State // ==================================== - struct Statistics - { - Statistics(): - mTotalRequests(0), - mCurrentRequests(0) - {} - - S32 mTotalRequests; - S32 mCurrentRequests; - }; - - static Statistics mStatistics; - }; // end class HttpRequest diff --git a/indra/llcorehttp/httpresponse.h b/indra/llcorehttp/httpresponse.h index 0bfa4585c7..b834085e5c 100644 --- a/indra/llcorehttp/httpresponse.h +++ b/indra/llcorehttp/httpresponse.h @@ -204,6 +204,15 @@ public: return mRequestUrl; } + void setRequestMethod(const std::string &method) + { + mRequestMethod = method; + } + + const std::string &getRequestMethod() const + { + return mRequestMethod; + } protected: // Response data here @@ -217,6 +226,7 @@ protected: unsigned int mRetries; unsigned int m503Retries; std::string mRequestUrl; + std::string mRequestMethod; TransferStats::ptr_t mStats; }; diff --git a/indra/llcorehttp/httpstats.cpp b/indra/llcorehttp/httpstats.cpp index 467d364885..b2de7f51ff 100644 --- a/indra/llcorehttp/httpstats.cpp +++ b/indra/llcorehttp/httpstats.cpp @@ -44,6 +44,7 @@ void HTTPStats::resetStats() mResutCodes.clear(); mDataDown.reset(); mDataUp.reset(); + mRequests = 0; } @@ -60,16 +61,41 @@ void HTTPStats::recordResultCode(S32 code) } +namespace +{ + std::string byte_count_converter(F32 bytes) + { + static const char unit_suffix[] = { 'B', 'K', 'M', 'G' }; + + F32 value = bytes; + int suffix = 0; + + while ((value > 1024.0) && (suffix < 3)) + { + value /= 1024.0; + ++suffix; + } + + std::stringstream out; + + out << std::setprecision(4) << value << unit_suffix[suffix]; + + return out.str(); + } +} + void HTTPStats::dumpStats() { std::stringstream out; - out << "HTTPCore Stats" << std::endl; - out << "Bytes Sent: " << mDataUp.getSum() << std::endl; - out << "Bytes Recv: " << mDataDown.getSum() << std::endl; + out << "HTTP DATA SUMMARY" << std::endl; + out << "HTTP Transfer counts:" << std::endl; + out << "Data Sent: " << byte_count_converter(mDataUp.getSum()) << " (" << mDataUp.getSum() << ")" << std::endl; + out << "Data Recv: " << byte_count_converter(mDataDown.getSum()) << " (" << mDataDown.getSum() << ")" << std::endl; + out << "Total requests: " << mRequests << "(request objects created)" << std::endl; + out << std::endl; out << "Result Codes:" << std::endl << "--- -----" << std::endl; - for (std::map::iterator it = mResutCodes.begin(); it != mResutCodes.end(); ++it) { out << (*it).first << " " << (*it).second << std::endl; diff --git a/indra/llcorehttp/httpstats.h b/indra/llcorehttp/httpstats.h index d4460bcfae..2c713cb548 100644 --- a/indra/llcorehttp/httpstats.h +++ b/indra/llcorehttp/httpstats.h @@ -55,6 +55,8 @@ namespace LLCore mDataUp.push(bytes); } + void recordHTTPRequest() { ++mRequests; } + void recordResultCode(S32 code); void dumpStats(); @@ -62,6 +64,8 @@ namespace LLCore StatsAccumulator mDataDown; StatsAccumulator mDataUp; + S32 mRequests; + std::map mResutCodes; }; diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp index 9bf38fb336..ac4b1310a4 100644 --- a/indra/llmessage/llcorehttputil.cpp +++ b/indra/llmessage/llcorehttputil.cpp @@ -84,7 +84,7 @@ void logMessageSuccess(std::string logAuth, std::string url, std::string message void logMessageFail(std::string logAuth, std::string url, std::string message) { - LL_WARNS() << logAuth << " Failure '" << message << "' for " << url << LL_ENDL; + LL_WARNS("CoreHTTP") << logAuth << " Failure '" << message << "' for " << url << LL_ENDL; } //========================================================================= @@ -279,12 +279,10 @@ void HttpCoroHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespons result = LLSD::emptyMap(); LLCore::HttpStatus::type_enum_t errType = status.getType(); - LL_WARNS() - << "\n--------------------------------------------------------------------------\n" - << " Error[" << status.toTerseString() << "] cannot access url '" << response->getRequestURL() - << "' because " << status.toString() - << "\n--------------------------------------------------------------------------" - << LL_ENDL; + LL_WARNS("CoreHTTP") + << " Error[" << status.toTerseString() << "] cannot "<< response->getRequestMethod() + << " to url '" << response->getRequestURL() + << "' because " << status.toString() << LL_ENDL; if ((errType >= 400) && (errType < 500)) { LLSD body = this->parseBody(response, parseSuccess); @@ -299,7 +297,6 @@ void HttpCoroHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespons result = body; } } - } } else @@ -323,7 +320,7 @@ void HttpCoroHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespons if (getBoolSetting(HTTP_LOGBODY_KEY)) { // commenting out, but keeping since this can be useful for debugging - LL_WARNS() << "Returned body=" << std::endl << httpStatus["error_body"].asString() << LL_ENDL; + LL_WARNS("CoreHTTP") << "Returned body=" << std::endl << httpStatus["error_body"].asString() << LL_ENDL; } } @@ -423,7 +420,7 @@ LLSD HttpCoroLLSDHandler::handleSuccess(LLCore::HttpResponse * response, LLCore: if (contentType && (HTTP_CONTENT_LLSD_XML == *contentType)) { std::string thebody = LLCoreHttpUtil::responseToString(response); - LL_WARNS() << "Failed to deserialize . " << response->getRequestURL() << " [status:" << response->getStatus().toString() << "] " + LL_WARNS("CoreHTTP") << "Failed to deserialize . " << response->getRequestURL() << " [status:" << response->getStatus().toString() << "] " << " body: " << thebody << LL_ENDL; // Replace the status with a new one indicating the failure. @@ -442,7 +439,7 @@ LLSD HttpCoroLLSDHandler::handleSuccess(LLCore::HttpResponse * response, LLCore: if (contentType && (HTTP_CONTENT_LLSD_XML == *contentType)) { std::string thebody = LLCoreHttpUtil::responseToString(response); - LL_WARNS() << "Failed to deserialize . " << response->getRequestURL() << " [status:" << response->getStatus().toString() << "] " + LL_WARNS("CoreHTTP") << "Failed to deserialize . " << response->getRequestURL() << " [status:" << response->getStatus().toString() << "] " << " body: " << thebody << LL_ENDL; // Replace the status with a new one indicating the failure. @@ -1210,7 +1207,7 @@ LLSD HttpCoroutineAdapter::buildImmediateErrorResult(const LLCore::HttpRequest:: const std::string &url) { LLCore::HttpStatus status = request->getStatus(); - LL_WARNS() << "Error posting to " << url << " Status=" << status.getStatus() << + LL_WARNS("CoreHTTP") << "Error posting to " << url << " Status=" << status.getStatus() << " message = " << status.getMessage() << LL_ENDL; // Mimic the status results returned from an http error that we had -- cgit v1.3 From 79856e655432a30f5bba2e8d7adecdc3626ce94f Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Mon, 14 Aug 2017 14:54:58 -0700 Subject: MAINT-7634: Feedback from code review, move enum to string converter to own function. --- indra/llcorehttp/_httpoprequest.cpp | 38 +++++++++++++++++++------------------ indra/llcorehttp/_httpoprequest.h | 4 +++- 2 files changed, 23 insertions(+), 19 deletions(-) (limited to 'indra/llcorehttp/_httpoprequest.cpp') diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index 36955f3797..f526af37b5 100644 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -247,24 +247,7 @@ void HttpOpRequest::visitNotifier(HttpRequest * request) response->setHeaders(mReplyHeaders); response->setRequestURL(mReqURL); - std::string method("UNKNOWN"); - - if (mReqMethod == HOR_COPY) - method = "COPY"; - else if (mReqMethod == HOR_DELETE) - method = "DELETE"; - else if (mReqMethod == HOR_GET) - method = "GET"; - else if (mReqMethod == HOR_MOVE) - method = "MOVE"; - else if (mReqMethod == HOR_PATCH) - method = "PATCH"; - else if (mReqMethod == HOR_POST) - method = "POST"; - else if (mReqMethod == HOR_PUT) - method = "PUT"; - - response->setRequestMethod(method); + response->setRequestMethod(methodToString(mReqMethod)); if (mReplyOffset || mReplyLength) { @@ -1161,6 +1144,25 @@ int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffe return 0; } +std::string HttpOpRequest::methodToString(const HttpOpRequest::EMethod &e) +{ + if (e == HOR_COPY) + return "COPY"; + else if (e == HOR_DELETE) + return "DELETE"; + else if (e == HOR_GET) + return "GET"; + else if (e == HOR_MOVE) + return "MOVE"; + else if (e == HOR_PATCH) + return "PATCH"; + else if (e == HOR_POST) + return "POST"; + else if (e == HOR_PUT) + return "PUT"; + + return "UNKNOWN"; +} } // end namespace LLCore diff --git a/indra/llcorehttp/_httpoprequest.h b/indra/llcorehttp/_httpoprequest.h index dbcc57d0fd..201c37d5c3 100644 --- a/indra/llcorehttp/_httpoprequest.h +++ b/indra/llcorehttp/_httpoprequest.h @@ -87,7 +87,8 @@ public: HOR_COPY, HOR_MOVE }; - + static std::string methodToString(const EMethod &); + virtual void stageFromRequest(HttpService *); virtual void stageFromReady(HttpService *); virtual void stageFromActive(HttpService *); @@ -235,6 +236,7 @@ public: }; // end class HttpOpRequest + /// HttpOpRequestCompare isn't an operation but a uniform comparison /// functor for STL containers that order by priority. Mainly /// used for the ready queue container but defined here. -- cgit v1.3 From 586d697475da239060abd8df030778fbdfb0cf51 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 29 Sep 2017 17:06:42 -0400 Subject: MAINT-7081: Try requesting HTTP/2 when a request wants pipelining. --- indra/llcorehttp/_httplibcurl.cpp | 32 ++++---- indra/llcorehttp/_httpoprequest.cpp | 151 ++++++++++++++---------------------- 2 files changed, 76 insertions(+), 107 deletions(-) (limited to 'indra/llcorehttp/_httpoprequest.cpp') diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp index c25e01a318..947a065d0a 100644 --- a/indra/llcorehttp/_httplibcurl.cpp +++ b/indra/llcorehttp/_httplibcurl.cpp @@ -40,6 +40,15 @@ namespace void check_curl_multi_code(CURLMcode code); void check_curl_multi_code(CURLMcode code, int curl_setopt_option); +// This is a template because different 'option' values require different +// types for 'ARG'. Just pass them through unchanged (by value). +template +void check_curl_multi_setopt(CURLM* handle, CURLMoption option, ARG argument) +{ + CURLMcode code = curl_multi_setopt(handle, option, argument); + check_curl_multi_code(code, option); +} + static const char * const LOG_CORE("CoreHttp"); } // end anonymous namespace @@ -466,41 +475,34 @@ void HttpLibcurl::policyUpdated(int policy_class) // Enable policy if stalled policy.stallPolicy(policy_class, false); mDirtyPolicy[policy_class] = false; - + if (options.mPipelining > 1) { // We'll try to do pipelining on this multihandle - code = curl_multi_setopt(multi_handle, + check_curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, 1L); - check_curl_multi_code(code, CURLMOPT_PIPELINING); - code = curl_multi_setopt(multi_handle, + check_curl_multi_setopt(multi_handle, CURLMOPT_MAX_PIPELINE_LENGTH, long(options.mPipelining)); - check_curl_multi_code(code, CURLMOPT_MAX_PIPELINE_LENGTH); - code = curl_multi_setopt(multi_handle, + check_curl_multi_setopt(multi_handle, CURLMOPT_MAX_HOST_CONNECTIONS, long(options.mPerHostConnectionLimit)); - check_curl_multi_code(code, CURLMOPT_MAX_HOST_CONNECTIONS); - code = curl_multi_setopt(multi_handle, + check_curl_multi_setopt(multi_handle, CURLMOPT_MAX_TOTAL_CONNECTIONS, long(options.mConnectionLimit)); - check_curl_multi_code(code, CURLMOPT_MAX_TOTAL_CONNECTIONS); } else { - code = curl_multi_setopt(multi_handle, + check_curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, 0L); - check_curl_multi_code(code, CURLMOPT_PIPELINING); - code = curl_multi_setopt(multi_handle, + check_curl_multi_setopt(multi_handle, CURLMOPT_MAX_HOST_CONNECTIONS, 0L); - check_curl_multi_code(code, CURLMOPT_MAX_HOST_CONNECTIONS); - code = curl_multi_setopt(multi_handle, + check_curl_multi_setopt(multi_handle, CURLMOPT_MAX_TOTAL_CONNECTIONS, long(options.mConnectionLimit)); - check_curl_multi_code(code, CURLMOPT_MAX_TOTAL_CONNECTIONS); } } else if (! mDirtyPolicy[policy_class]) diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index f526af37b5..dae795c41c 100644 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -108,6 +108,15 @@ void os_strlower(char * str); // Error testing and reporting for libcurl status codes void check_curl_easy_code(CURLcode code, int curl_setopt_option); +// This is a template because different 'option' values require different +// types for 'ARG'. Just pass them through unchanged (by value). +template +void check_curl_easy_setopt(CURL* handle, CURLoption option, ARG argument) +{ + CURLcode code = curl_easy_setopt(handle, option, argument); + check_curl_easy_code(code, option); +} + static const char * const LOG_CORE("CoreHttp"); } // end anonymous namespace @@ -491,45 +500,28 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) return HttpStatus(HttpStatus::LLCORE, HE_BAD_ALLOC); } - code = curl_easy_setopt(mCurlHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); - check_curl_easy_code(code, CURLOPT_IPRESOLVE); - code = curl_easy_setopt(mCurlHandle, CURLOPT_NOSIGNAL, 1); - check_curl_easy_code(code, CURLOPT_NOSIGNAL); - code = curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1); - check_curl_easy_code(code, CURLOPT_NOPROGRESS); - code = curl_easy_setopt(mCurlHandle, CURLOPT_URL, mReqURL.c_str()); - check_curl_easy_code(code, CURLOPT_URL); - code = curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, getHandle()); - check_curl_easy_code(code, CURLOPT_PRIVATE); - code = curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, ""); - check_curl_easy_code(code, CURLOPT_ENCODING); - - code = curl_easy_setopt(mCurlHandle, CURLOPT_AUTOREFERER, 1); - check_curl_easy_code(code, CURLOPT_AUTOREFERER); - code = curl_easy_setopt(mCurlHandle, CURLOPT_MAXREDIRS, HTTP_REDIRECTS_DEFAULT); - check_curl_easy_code(code, CURLOPT_MAXREDIRS); - code = curl_easy_setopt(mCurlHandle, CURLOPT_WRITEFUNCTION, writeCallback); - check_curl_easy_code(code, CURLOPT_WRITEFUNCTION); - code = curl_easy_setopt(mCurlHandle, CURLOPT_WRITEDATA, getHandle()); - check_curl_easy_code(code, CURLOPT_WRITEDATA); - code = curl_easy_setopt(mCurlHandle, CURLOPT_READFUNCTION, readCallback); - check_curl_easy_code(code, CURLOPT_READFUNCTION); - code = curl_easy_setopt(mCurlHandle, CURLOPT_READDATA, getHandle()); - check_curl_easy_code(code, CURLOPT_READDATA); - code = curl_easy_setopt(mCurlHandle, CURLOPT_SEEKFUNCTION, seekCallback); - check_curl_easy_code(code, CURLOPT_SEEKFUNCTION); - code = curl_easy_setopt(mCurlHandle, CURLOPT_SEEKDATA, getHandle()); - check_curl_easy_code(code, CURLOPT_SEEKDATA); - - code = curl_easy_setopt(mCurlHandle, CURLOPT_COOKIEFILE, ""); - check_curl_easy_code(code, CURLOPT_COOKIEFILE); + check_curl_easy_setopt(mCurlHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + check_curl_easy_setopt(mCurlHandle, CURLOPT_NOSIGNAL, 1); + check_curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1); + check_curl_easy_setopt(mCurlHandle, CURLOPT_URL, mReqURL.c_str()); + check_curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, getHandle()); + check_curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, ""); + + check_curl_easy_setopt(mCurlHandle, CURLOPT_AUTOREFERER, 1); + check_curl_easy_setopt(mCurlHandle, CURLOPT_MAXREDIRS, HTTP_REDIRECTS_DEFAULT); + check_curl_easy_setopt(mCurlHandle, CURLOPT_WRITEFUNCTION, writeCallback); + check_curl_easy_setopt(mCurlHandle, CURLOPT_WRITEDATA, getHandle()); + check_curl_easy_setopt(mCurlHandle, CURLOPT_READFUNCTION, readCallback); + check_curl_easy_setopt(mCurlHandle, CURLOPT_READDATA, getHandle()); + check_curl_easy_setopt(mCurlHandle, CURLOPT_SEEKFUNCTION, seekCallback); + check_curl_easy_setopt(mCurlHandle, CURLOPT_SEEKDATA, getHandle()); + + check_curl_easy_setopt(mCurlHandle, CURLOPT_COOKIEFILE, ""); if (gpolicy.mSslCtxCallback) { - code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_CTX_FUNCTION, curlSslCtxCallback); - check_curl_easy_code(code, CURLOPT_SSL_CTX_FUNCTION); - code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_CTX_DATA, getHandle()); - check_curl_easy_code(code, CURLOPT_SSL_CTX_DATA); + check_curl_easy_setopt(mCurlHandle, CURLOPT_SSL_CTX_FUNCTION, curlSslCtxCallback); + check_curl_easy_setopt(mCurlHandle, CURLOPT_SSL_CTX_DATA, getHandle()); mCallbackSSLVerify = gpolicy.mSslCtxCallback; } @@ -547,16 +539,12 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) dnsCacheTimeout = mReqOptions->getDNSCacheTimeout(); nobody = mReqOptions->getHeadersOnly() ? 1L : 0L; } - code = curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, follow_redirect); - check_curl_easy_code(code, CURLOPT_FOLLOWLOCATION); + check_curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, follow_redirect); - code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYPEER, sslPeerV); - check_curl_easy_code(code, CURLOPT_SSL_VERIFYPEER); - code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYHOST, sslHostV); - check_curl_easy_code(code, CURLOPT_SSL_VERIFYHOST); + check_curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYPEER, sslPeerV); + check_curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYHOST, sslHostV); - code = curl_easy_setopt(mCurlHandle, CURLOPT_NOBODY, nobody); - check_curl_easy_code(code, CURLOPT_NOBODY); + check_curl_easy_setopt(mCurlHandle, CURLOPT_NOBODY, nobody); // The Linksys WRT54G V5 router has an issue with frequent // DNS lookups from LAN machines. If they happen too often, @@ -564,8 +552,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) // about 700 or so requests and starts issuing TCP RSTs to // new connections. Reuse the DNS lookups for even a few // seconds and no RSTs. - code = curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, dnsCacheTimeout); - check_curl_easy_code(code, CURLOPT_DNS_CACHE_TIMEOUT); + check_curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, dnsCacheTimeout); if (gpolicy.mUseLLProxy) { @@ -588,81 +575,66 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) { // *TODO: This is fine for now but get fuller socks5/ // authentication thing going later.... - code = curl_easy_setopt(mCurlHandle, CURLOPT_PROXY, gpolicy.mHttpProxy.c_str()); - check_curl_easy_code(code, CURLOPT_PROXY); - code = curl_easy_setopt(mCurlHandle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); - check_curl_easy_code(code, CURLOPT_PROXYTYPE); + check_curl_easy_setopt(mCurlHandle, CURLOPT_PROXY, gpolicy.mHttpProxy.c_str()); + check_curl_easy_setopt(mCurlHandle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); } if (gpolicy.mCAPath.size()) { - code = curl_easy_setopt(mCurlHandle, CURLOPT_CAPATH, gpolicy.mCAPath.c_str()); - check_curl_easy_code(code, CURLOPT_CAPATH); + check_curl_easy_setopt(mCurlHandle, CURLOPT_CAPATH, gpolicy.mCAPath.c_str()); } if (gpolicy.mCAFile.size()) { - code = curl_easy_setopt(mCurlHandle, CURLOPT_CAINFO, gpolicy.mCAFile.c_str()); - check_curl_easy_code(code, CURLOPT_CAINFO); + check_curl_easy_setopt(mCurlHandle, CURLOPT_CAINFO, gpolicy.mCAFile.c_str()); } switch (mReqMethod) { case HOR_GET: if (nobody == 0) - code = curl_easy_setopt(mCurlHandle, CURLOPT_HTTPGET, 1); - check_curl_easy_code(code, CURLOPT_HTTPGET); + check_curl_easy_setopt(mCurlHandle, CURLOPT_HTTPGET, 1); break; case HOR_POST: { - code = curl_easy_setopt(mCurlHandle, CURLOPT_POST, 1); - check_curl_easy_code(code, CURLOPT_POST); - code = curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, ""); - check_curl_easy_code(code, CURLOPT_ENCODING); + check_curl_easy_setopt(mCurlHandle, CURLOPT_POST, 1); + check_curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, ""); long data_size(0); if (mReqBody) { data_size = mReqBody->size(); } - code = curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, static_cast(NULL)); - check_curl_easy_code(code, CURLOPT_POSTFIELDS); - code = curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDSIZE, data_size); - check_curl_easy_code(code, CURLOPT_POSTFIELDSIZE); + check_curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, static_cast(NULL)); + check_curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDSIZE, data_size); mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:"); } break; case HOR_PATCH: - code = curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "PATCH"); - check_curl_easy_code(code, CURLOPT_CUSTOMREQUEST); + check_curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "PATCH"); // fall through. The rest is the same as PUT case HOR_PUT: { - code = curl_easy_setopt(mCurlHandle, CURLOPT_UPLOAD, 1); - check_curl_easy_code(code, CURLOPT_UPLOAD); + check_curl_easy_setopt(mCurlHandle, CURLOPT_UPLOAD, 1); long data_size(0); if (mReqBody) { data_size = mReqBody->size(); } - code = curl_easy_setopt(mCurlHandle, CURLOPT_INFILESIZE, data_size); - check_curl_easy_code(code, CURLOPT_INFILESIZE); + check_curl_easy_setopt(mCurlHandle, CURLOPT_INFILESIZE, data_size); mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:"); } break; case HOR_DELETE: - code = curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "DELETE"); - check_curl_easy_code(code, CURLOPT_CUSTOMREQUEST); + check_curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "DELETE"); break; case HOR_COPY: - code = curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "COPY"); - check_curl_easy_code(code, CURLOPT_CUSTOMREQUEST); + check_curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "COPY"); break; case HOR_MOVE: - code = curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "MOVE"); - check_curl_easy_code(code, CURLOPT_CUSTOMREQUEST); + check_curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "MOVE"); break; default: @@ -680,12 +652,9 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) // Tracing if (mTracing >= HTTP_TRACE_CURL_HEADERS) { - code = curl_easy_setopt(mCurlHandle, CURLOPT_VERBOSE, 1); - check_curl_easy_code(code, CURLOPT_VERBOSE); - code = curl_easy_setopt(mCurlHandle, CURLOPT_DEBUGDATA, this); - check_curl_easy_code(code, CURLOPT_DEBUGDATA); - code = curl_easy_setopt(mCurlHandle, CURLOPT_DEBUGFUNCTION, debugCallback); - check_curl_easy_code(code, CURLOPT_DEBUGFUNCTION); + check_curl_easy_setopt(mCurlHandle, CURLOPT_VERBOSE, 1); + check_curl_easy_setopt(mCurlHandle, CURLOPT_DEBUGDATA, this); + check_curl_easy_setopt(mCurlHandle, CURLOPT_DEBUGFUNCTION, debugCallback); } // There's a CURLOPT for this now... @@ -762,6 +731,9 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) // // xfer_timeout *= cpolicy.mPipelining; xfer_timeout *= 2L; + + // Also try requesting HTTP/2. + check_curl_easy_setopt(mCurlHandle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); } // *DEBUG: Enable following override for timeout handling and "[curl:bugs] #1420" tests //if (cpolicy.mPipelining) @@ -769,10 +741,8 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) // xfer_timeout = 1L; // timeout = 1L; //} - code = curl_easy_setopt(mCurlHandle, CURLOPT_TIMEOUT, xfer_timeout); - check_curl_easy_code(code, CURLOPT_TIMEOUT); - code = curl_easy_setopt(mCurlHandle, CURLOPT_CONNECTTIMEOUT, timeout); - check_curl_easy_code(code, CURLOPT_CONNECTTIMEOUT); + check_curl_easy_setopt(mCurlHandle, CURLOPT_TIMEOUT, xfer_timeout); + check_curl_easy_setopt(mCurlHandle, CURLOPT_CONNECTTIMEOUT, timeout); // Request headers if (mReqHeaders) @@ -780,15 +750,12 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) // Caller's headers last to override mCurlHeaders = append_headers_to_slist(mReqHeaders, mCurlHeaders); } - code = curl_easy_setopt(mCurlHandle, CURLOPT_HTTPHEADER, mCurlHeaders); - check_curl_easy_code(code, CURLOPT_HTTPHEADER); + check_curl_easy_setopt(mCurlHandle, CURLOPT_HTTPHEADER, mCurlHeaders); if (mProcFlags & (PF_SCAN_RANGE_HEADER | PF_SAVE_HEADERS | PF_USE_RETRY_AFTER)) { - code = curl_easy_setopt(mCurlHandle, CURLOPT_HEADERFUNCTION, headerCallback); - check_curl_easy_code(code, CURLOPT_HEADERFUNCTION); - code = curl_easy_setopt(mCurlHandle, CURLOPT_HEADERDATA, this); - check_curl_easy_code(code, CURLOPT_HEADERDATA); + check_curl_easy_setopt(mCurlHandle, CURLOPT_HEADERFUNCTION, headerCallback); + check_curl_easy_setopt(mCurlHandle, CURLOPT_HEADERDATA, this); } if (status) -- cgit v1.3 From 6b508cd9d45d8c74477efb0b97b1cbcccb714e78 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 30 Sep 2017 22:05:21 -0400 Subject: MAINT-7081: Eliminate unused variable errors after new refactoring. The new helper functions check_curl_easy_setopt() and check_curl_multi_setopt() encapsulate the pervasive idiom: code = curl_{easy,multi}_setopt(handle, option, arg); check_curl_{easy,multi}_code(code, option); But since each of these helper functions contains its own local CURL{,M}code variable 'code', having a caller-scope variable reused for every such call is no longer necessary -- in fact is no longer used at all. That produces a fatal warning with MSVC. Get rid of those now-unused variables. --- indra/llcorehttp/_httplibcurl.cpp | 1 - indra/llcorehttp/_httpoprequest.cpp | 2 -- 2 files changed, 3 deletions(-) (limited to 'indra/llcorehttp/_httpoprequest.cpp') diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp index 947a065d0a..abd304f6a5 100644 --- a/indra/llcorehttp/_httplibcurl.cpp +++ b/indra/llcorehttp/_httplibcurl.cpp @@ -470,7 +470,6 @@ void HttpLibcurl::policyUpdated(int policy_class) HttpPolicyClass & options(policy.getClassOptions(policy_class)); CURLM * multi_handle(mMultiHandles[policy_class]); - CURLMcode code; // Enable policy if stalled policy.stallPolicy(policy_class, false); diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index dae795c41c..1049c9da96 100644 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -460,8 +460,6 @@ void HttpOpRequest::setupCommon(HttpRequest::policy_t policy_id, // *TODO: Move this to _httplibcurl where it belongs. HttpStatus HttpOpRequest::prepareRequest(HttpService * service) { - CURLcode code; - // Scrub transport and result data for retried op case mCurlActive = false; mCurlHandle = NULL; -- cgit v1.3 From ead19aa22cb9cb297ca1c89e96daa85101c1158f Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 24 Oct 2017 15:57:36 -0400 Subject: MAINT-7081: Only request HTTP2 with $VIEWERASSET override (testing) --- indra/llcorehttp/_httpoprequest.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indra/llcorehttp/_httpoprequest.cpp') diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index 1ef7730c8e..cc49a2af80 100644 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -736,6 +736,10 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) xfer_timeout *= 2L; // Also try requesting HTTP/2. +/******************************/ + // but for test purposes, only if overriding VIEWERASSET + if (getenv("VIEWERASSET")) +/******************************/ check_curl_easy_setopt(mCurlHandle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); } // *DEBUG: Enable following override for timeout handling and "[curl:bugs] #1420" tests -- cgit v1.3