diff options
Diffstat (limited to 'indra')
97 files changed, 1359 insertions, 1316 deletions
diff --git a/indra/llaudio/llaudioengine_fmod.cpp b/indra/llaudio/llaudioengine_fmod.cpp index 88dfdb9c24..a40de9fa68 100644 --- a/indra/llaudio/llaudioengine_fmod.cpp +++ b/indra/llaudio/llaudioengine_fmod.cpp @@ -673,7 +673,7 @@ bool LLAudioBufferFMOD::loadWAV(const std::string& filename) return false; } - if (!LLAPRFile::isExist(filename, LL_APR_RPB)) + if (!LLAPRFile::isExist(filename, NULL, LL_APR_RPB)) { // File not found, abort. return false; diff --git a/indra/llaudio/llvorbisencode.cpp b/indra/llaudio/llvorbisencode.cpp index 44eeea0ca4..0e0c80a456 100644 --- a/indra/llaudio/llvorbisencode.cpp +++ b/indra/llaudio/llvorbisencode.cpp @@ -82,7 +82,8 @@ S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& erro error_msg.clear(); //******************************** - LLAPRFile infile(in_fname, LL_APR_RB); + LLAPRFile infile ; + infile.open(in_fname,LL_APR_RB); //******************************** if (!infile.getFileHandle()) { @@ -232,7 +233,8 @@ S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname S32 data_left = 0; - LLAPRFile infile(in_fname,LL_APR_RB); + LLAPRFile infile ; + infile.open(in_fname,LL_APR_RB); if (!infile.getFileHandle()) { llwarns << "Couldn't open temporary ogg file for writing: " << in_fname @@ -240,7 +242,8 @@ S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname return(LLVORBISENC_SOURCE_OPEN_ERR); } - LLAPRFile outfile(out_fname, LL_APR_WPB); + LLAPRFile outfile ; + outfile.open(out_fname,LL_APR_WPB); if (!outfile.getFileHandle()) { llwarns << "Couldn't open upload sound file for reading: " << in_fname diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp index c3c7f03247..f3cf950afa 100644 --- a/indra/llcharacter/llbvhloader.cpp +++ b/indra/llcharacter/llbvhloader.cpp @@ -219,7 +219,8 @@ ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName) //-------------------------------------------------------------------- std::string path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,fileName); - LLAPRFile infile(path, LL_APR_R); + LLAPRFile infile ; + infile.open(path, LL_APR_R); apr_file_t *fp = infile.getFileHandle(); if (!fp) return E_ST_NO_XLT_FILE; diff --git a/indra/llcharacter/llkeyframemotionparam.cpp b/indra/llcharacter/llkeyframemotionparam.cpp index c3d5dec875..82fe8971f5 100644 --- a/indra/llcharacter/llkeyframemotionparam.cpp +++ b/indra/llcharacter/llkeyframemotionparam.cpp @@ -351,7 +351,8 @@ BOOL LLKeyframeMotionParam::loadMotions() // open the file //------------------------------------------------------------------------- S32 fileSize = 0; - LLAPRFile infile(path, LL_APR_R, &fileSize); + LLAPRFile infile ; + infile.open(path, LL_APR_R, NULL, &fileSize); apr_file_t* fp = infile.getFileHandle() ; if (!fp || fileSize == 0) { diff --git a/indra/llcharacter/llstatemachine.cpp b/indra/llcharacter/llstatemachine.cpp index dcc4ff5f0e..e0454131a5 100644 --- a/indra/llcharacter/llstatemachine.cpp +++ b/indra/llcharacter/llstatemachine.cpp @@ -204,7 +204,8 @@ LLFSMState* LLStateDiagram::getState(U32 state_id) BOOL LLStateDiagram::saveDotFile(const std::string& filename) { - LLAPRFile outfile(filename, LL_APR_W); + LLAPRFile outfile ; + outfile.open(filename, LL_APR_W); apr_file_t* dot_file = outfile.getFileHandle() ; if (!dot_file) diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 6f39aba976..0a3eaec5c5 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -31,7 +31,6 @@ set(llcommon_SOURCE_FILES llallocator_heap_profile.cpp llapp.cpp llapr.cpp - llaprpool.cpp llassettype.cpp llavatarname.cpp llbase32.cpp @@ -81,7 +80,6 @@ set(llcommon_SOURCE_FILES llrand.cpp llrefcount.cpp llrun.cpp - llscopedvolatileaprpool.h llsd.cpp llsdserialize.cpp llsdserialize_xml.cpp @@ -124,7 +122,6 @@ set(llcommon_HEADER_FILES llavatarname.h llapp.h llapr.h - llaprpool.h llassettype.h llassoclist.h llavatarconstants.h diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index a8b7106078..ed192a9975 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -137,6 +137,10 @@ void LLApp::commonCtor() mOptions.append(sd); } + // Make sure we clean up APR when we exit + // Don't need to do this if we're cleaning up APR in the destructor + //atexit(ll_cleanup_apr); + // Set the application to this instance. sApplication = this; diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index 1e4a51102e..d1c44c9403 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -29,8 +29,212 @@ #include "linden_common.h" #include "llapr.h" #include "apr_dso.h" -#include "llscopedvolatileaprpool.h" +apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool +LLVolatileAPRPool *LLAPRFile::sAPRFilePoolp = NULL ; //global volatile APR memory pool. +apr_thread_mutex_t *gLogMutexp = NULL; +apr_thread_mutex_t *gCallStacksLogMutexp = NULL; + +const S32 FULL_VOLATILE_APR_POOL = 1024 ; //number of references to LLVolatileAPRPool + +void ll_init_apr() +{ + if (!gAPRPoolp) + { + // Initialize APR and create the global pool + apr_initialize(); + apr_pool_create(&gAPRPoolp, NULL); + + // Initialize the logging mutex + apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp); + apr_thread_mutex_create(&gCallStacksLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp); + } + + if(!LLAPRFile::sAPRFilePoolp) + { + LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ; + } +} + + +void ll_cleanup_apr() +{ + LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL; + + if (gLogMutexp) + { + // Clean up the logging mutex + + // All other threads NEED to be done before we clean up APR, so this is okay. + apr_thread_mutex_destroy(gLogMutexp); + gLogMutexp = NULL; + } + if (gCallStacksLogMutexp) + { + // Clean up the logging mutex + + // All other threads NEED to be done before we clean up APR, so this is okay. + apr_thread_mutex_destroy(gCallStacksLogMutexp); + gCallStacksLogMutexp = NULL; + } + if (gAPRPoolp) + { + apr_pool_destroy(gAPRPoolp); + gAPRPoolp = NULL; + } + if (LLAPRFile::sAPRFilePoolp) + { + delete LLAPRFile::sAPRFilePoolp ; + LLAPRFile::sAPRFilePoolp = NULL ; + } + apr_terminate(); +} + +// +// +//LLAPRPool +// +LLAPRPool::LLAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag) + : mParent(parent), + mReleasePoolFlag(releasePoolFlag), + mMaxSize(size), + mPool(NULL) +{ + createAPRPool() ; +} + +LLAPRPool::~LLAPRPool() +{ + releaseAPRPool() ; +} + +void LLAPRPool::createAPRPool() +{ + if(mPool) + { + return ; + } + + mStatus = apr_pool_create(&mPool, mParent); + ll_apr_warn_status(mStatus) ; + + if(mMaxSize > 0) //size is the number of blocks (which is usually 4K), NOT bytes. + { + apr_allocator_t *allocator = apr_pool_allocator_get(mPool); + if (allocator) + { + apr_allocator_max_free_set(allocator, mMaxSize) ; + } + } +} + +void LLAPRPool::releaseAPRPool() +{ + if(!mPool) + { + return ; + } + + if(!mParent || mReleasePoolFlag) + { + apr_pool_destroy(mPool) ; + mPool = NULL ; + } +} + +//virtual +apr_pool_t* LLAPRPool::getAPRPool() +{ + return mPool ; +} + +LLVolatileAPRPool::LLVolatileAPRPool(BOOL is_local, apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag) + : LLAPRPool(parent, size, releasePoolFlag), + mNumActiveRef(0), + mNumTotalRef(0), + mMutexPool(NULL), + mMutexp(NULL) +{ + //create mutex + if(!is_local) //not a local apr_pool, that is: shared by multiple threads. + { + apr_pool_create(&mMutexPool, NULL); // Create a pool for mutex + apr_thread_mutex_create(&mMutexp, APR_THREAD_MUTEX_UNNESTED, mMutexPool); + } +} + +LLVolatileAPRPool::~LLVolatileAPRPool() +{ + //delete mutex + if(mMutexp) + { + apr_thread_mutex_destroy(mMutexp); + apr_pool_destroy(mMutexPool); + } +} + +// +//define this virtual function to avoid any mistakenly calling LLAPRPool::getAPRPool(). +// +//virtual +apr_pool_t* LLVolatileAPRPool::getAPRPool() +{ + return LLVolatileAPRPool::getVolatileAPRPool() ; +} + +apr_pool_t* LLVolatileAPRPool::getVolatileAPRPool() +{ + LLScopedLock lock(mMutexp) ; + + mNumTotalRef++ ; + mNumActiveRef++ ; + + if(!mPool) + { + createAPRPool() ; + } + + return mPool ; +} + +void LLVolatileAPRPool::clearVolatileAPRPool() +{ + LLScopedLock lock(mMutexp) ; + + if(mNumActiveRef > 0) + { + mNumActiveRef--; + if(mNumActiveRef < 1) + { + if(isFull()) + { + mNumTotalRef = 0 ; + + //destroy the apr_pool. + releaseAPRPool() ; + } + else + { + //This does not actually free the memory, + //it just allows the pool to re-use this memory for the next allocation. + apr_pool_clear(mPool) ; + } + } + } + else + { + llassert_always(mNumActiveRef > 0) ; + } + + //paranoia check if the pool is jammed. + //will remove the check before going to release. + llassert_always(mNumTotalRef < (FULL_VOLATILE_APR_POOL << 2)) ; +} + +BOOL LLVolatileAPRPool::isFull() +{ + return mNumTotalRef > FULL_VOLATILE_APR_POOL ; +} //--------------------------------------------------------------------- // // LLScopedLock @@ -109,17 +313,15 @@ void ll_apr_assert_status(apr_status_t status, apr_dso_handle_t *handle) // LLAPRFile::LLAPRFile() : mFile(NULL), - mVolatileFilePoolp(NULL), - mRegularFilePoolp(NULL) + mCurrentFilePoolp(NULL) { } -LLAPRFile::LLAPRFile(std::string const& filename, apr_int32_t flags, S32* sizep, access_t access_type) +LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool) : mFile(NULL), - mVolatileFilePoolp(NULL), - mRegularFilePoolp(NULL) + mCurrentFilePoolp(NULL) { - open(filename, flags, access_type, sizep); + open(filename, flags, pool); } LLAPRFile::~LLAPRFile() @@ -136,58 +338,36 @@ apr_status_t LLAPRFile::close() mFile = NULL ; } - if (mVolatileFilePoolp) + if(mCurrentFilePoolp) { - mVolatileFilePoolp->clearVolatileAPRPool() ; - mVolatileFilePoolp = NULL ; - } - - if (mRegularFilePoolp) - { - delete mRegularFilePoolp; - mRegularFilePoolp = NULL; + mCurrentFilePoolp->clearVolatileAPRPool() ; + mCurrentFilePoolp = NULL ; } return ret ; } -apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, access_t access_type, S32* sizep) +apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool, S32* sizep) { - llassert_always(!mFile); - llassert_always(!mVolatileFilePoolp && !mRegularFilePoolp); + apr_status_t s ; - apr_status_t status; - { - apr_pool_t* apr_file_open_pool; // The use of apr_pool_t is OK here. - // This is a temporary variable for a pool that is passed directly to apr_file_open below. - if (access_type == short_lived) - { - // Use a "volatile" thread-local pool. - mVolatileFilePoolp = &LLThreadLocalData::tldata().mVolatileAPRPool; - // Access the pool and increment its reference count. - // The reference count of LLVolatileAPRPool objects will be decremented - // again in LLAPRFile::close by calling mVolatileFilePoolp->clearVolatileAPRPool(). - apr_file_open_pool = mVolatileFilePoolp->getVolatileAPRPool(); - } - else - { - mRegularFilePoolp = new LLAPRPool(LLThreadLocalData::tldata().mRootPool); - apr_file_open_pool = (*mRegularFilePoolp)(); - } - status = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, apr_file_open_pool); - } - if (status != APR_SUCCESS || !mFile) + //check if already open some file + llassert_always(!mFile) ; + llassert_always(!mCurrentFilePoolp) ; + + apr_pool_t* apr_pool = pool ? pool->getVolatileAPRPool() : NULL ; + s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, getAPRFilePool(apr_pool)); + + if (s != APR_SUCCESS || !mFile) { mFile = NULL ; - close() ; + if (sizep) { *sizep = 0; } - return status; } - - if (sizep) + else if (sizep) { S32 file_size = 0; apr_off_t offset = 0; @@ -201,7 +381,49 @@ apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, acc *sizep = file_size; } - return status; + if(!mCurrentFilePoolp) + { + mCurrentFilePoolp = pool ; + + if(!mFile) + { + close() ; + } + } + + return s ; +} + +//use gAPRPoolp. +apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, BOOL use_global_pool) +{ + apr_status_t s; + + //check if already open some file + llassert_always(!mFile) ; + llassert_always(!mCurrentFilePoolp) ; + llassert_always(use_global_pool) ; //be aware of using gAPRPoolp. + + s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, gAPRPoolp); + if (s != APR_SUCCESS || !mFile) + { + mFile = NULL ; + close() ; + return s; + } + + return s; +} + +apr_pool_t* LLAPRFile::getAPRFilePool(apr_pool_t* pool) +{ + if(!pool) + { + mCurrentFilePoolp = sAPRFilePoolp ; + return mCurrentFilePoolp->getVolatileAPRPool() ; + } + + return pool ; } // File I/O @@ -260,6 +482,45 @@ S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset) // //static +apr_status_t LLAPRFile::close(apr_file_t* file_handle, LLVolatileAPRPool* pool) +{ + apr_status_t ret = APR_SUCCESS ; + if(file_handle) + { + ret = apr_file_close(file_handle); + file_handle = NULL ; + } + + if(pool) + { + pool->clearVolatileAPRPool() ; + } + + return ret ; +} + +//static +apr_file_t* LLAPRFile::open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags) +{ + apr_status_t s; + apr_file_t* file_handle ; + + pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; + + s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool()); + if (s != APR_SUCCESS || !file_handle) + { + ll_apr_warn_status(s); + LL_WARNS("APR") << " Attempting to open filename: " << filename << LL_ENDL; + file_handle = NULL ; + close(file_handle, pool) ; + return NULL; + } + + return file_handle ; +} + +//static S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset) { if(!file_handle) @@ -292,15 +553,13 @@ S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset) } //static -S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes) +S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool) { - apr_file_t* file_handle; - LLScopedVolatileAPRPool pool; - apr_status_t s = apr_file_open(&file_handle, filename.c_str(), APR_READ|APR_BINARY, APR_OS_DEFAULT, pool); - if (s != APR_SUCCESS || !file_handle) + //***************************************** + apr_file_t* file_handle = open(filename, pool, APR_READ|APR_BINARY); + //***************************************** + if (!file_handle) { - ll_apr_warn_status(s); - LL_WARNS("APR") << " while attempting to open file \"" << filename << '"' << LL_ENDL; return 0; } @@ -330,13 +589,14 @@ S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nb } } - apr_file_close(file_handle); - + //***************************************** + close(file_handle, pool) ; + //***************************************** return (S32)bytes_read; } //static -S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes) +S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool) { apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY; if (offset < 0) @@ -345,13 +605,11 @@ S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 n offset = 0; } - apr_file_t* file_handle; - LLScopedVolatileAPRPool pool; - apr_status_t s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool); - if (s != APR_SUCCESS || !file_handle) + //***************************************** + apr_file_t* file_handle = open(filename, pool, flags); + //***************************************** + if (!file_handle) { - ll_apr_warn_status(s); - LL_WARNS("APR") << " while attempting to open file \"" << filename << '"' << LL_ENDL; return 0; } @@ -381,18 +639,21 @@ S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 n } } - apr_file_close(file_handle); + //***************************************** + LLAPRFile::close(file_handle, pool); + //***************************************** return (S32)bytes_written; } //static -bool LLAPRFile::remove(const std::string& filename) +bool LLAPRFile::remove(const std::string& filename, LLVolatileAPRPool* pool) { apr_status_t s; - LLScopedVolatileAPRPool pool; - s = apr_file_remove(filename.c_str(), pool); + pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; + s = apr_file_remove(filename.c_str(), pool->getVolatileAPRPool()); + pool->clearVolatileAPRPool() ; if (s != APR_SUCCESS) { @@ -404,12 +665,13 @@ bool LLAPRFile::remove(const std::string& filename) } //static -bool LLAPRFile::rename(const std::string& filename, const std::string& newname) +bool LLAPRFile::rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool) { apr_status_t s; - LLScopedVolatileAPRPool pool; - s = apr_file_rename(filename.c_str(), newname.c_str(), pool); + pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; + s = apr_file_rename(filename.c_str(), newname.c_str(), pool->getVolatileAPRPool()); + pool->clearVolatileAPRPool() ; if (s != APR_SUCCESS) { @@ -421,44 +683,49 @@ bool LLAPRFile::rename(const std::string& filename, const std::string& newname) } //static -bool LLAPRFile::isExist(const std::string& filename, apr_int32_t flags) +bool LLAPRFile::isExist(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags) { - apr_file_t* file_handle; + apr_file_t* apr_file; apr_status_t s; - LLScopedVolatileAPRPool pool; - s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool); + pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; + s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool()); - if (s != APR_SUCCESS || !file_handle) + if (s != APR_SUCCESS || !apr_file) { + pool->clearVolatileAPRPool() ; return false; } else { - apr_file_close(file_handle); + apr_file_close(apr_file) ; + pool->clearVolatileAPRPool() ; return true; } } //static -S32 LLAPRFile::size(const std::string& filename) +S32 LLAPRFile::size(const std::string& filename, LLVolatileAPRPool* pool) { - apr_file_t* file_handle; + apr_file_t* apr_file; apr_finfo_t info; apr_status_t s; - LLScopedVolatileAPRPool pool; - s = apr_file_open(&file_handle, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool); + pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; + s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool->getVolatileAPRPool()); - if (s != APR_SUCCESS || !file_handle) + if (s != APR_SUCCESS || !apr_file) { + pool->clearVolatileAPRPool() ; + return 0; } else { - apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, file_handle); + apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, apr_file); - apr_file_close(file_handle) ; + apr_file_close(apr_file) ; + pool->clearVolatileAPRPool() ; if (s == APR_SUCCESS) { @@ -472,29 +739,31 @@ S32 LLAPRFile::size(const std::string& filename) } //static -bool LLAPRFile::makeDir(const std::string& dirname) +bool LLAPRFile::makeDir(const std::string& dirname, LLVolatileAPRPool* pool) { apr_status_t s; - LLScopedVolatileAPRPool pool; - s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool); + pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; + s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool->getVolatileAPRPool()); + pool->clearVolatileAPRPool() ; if (s != APR_SUCCESS) { ll_apr_warn_status(s); - LL_WARNS("APR") << " while attempting to make directory: " << dirname << LL_ENDL; + LL_WARNS("APR") << " Attempting to make directory: " << dirname << LL_ENDL; return false; } return true; } //static -bool LLAPRFile::removeDir(const std::string& dirname) +bool LLAPRFile::removeDir(const std::string& dirname, LLVolatileAPRPool* pool) { apr_status_t s; - LLScopedVolatileAPRPool pool; - s = apr_file_remove(dirname.c_str(), pool); + pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; + s = apr_file_remove(dirname.c_str(), pool->getVolatileAPRPool()); + pool->clearVolatileAPRPool() ; if (s != APR_SUCCESS) { diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h index 3f846f1314..af33ce666f 100644 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -50,9 +50,71 @@ #include "apr_atomic.h" #include "llstring.h" +extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp; +extern apr_thread_mutex_t* gCallStacksLogMutexp; + struct apr_dso_handle_t; -class LLAPRPool; -class LLVolatileAPRPool; + +/** + * @brief initialize the common apr constructs -- apr itself, the + * global pool, and a mutex. + */ +void LL_COMMON_API ll_init_apr(); + +/** + * @brief Cleanup those common apr constructs. + */ +void LL_COMMON_API ll_cleanup_apr(); + +// +//LL apr_pool +//manage apr_pool_t, destroy allocated apr_pool in the destruction function. +// +class LL_COMMON_API LLAPRPool +{ +public: + LLAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE) ; + virtual ~LLAPRPool() ; + + virtual apr_pool_t* getAPRPool() ; + apr_status_t getStatus() {return mStatus ; } + +protected: + void releaseAPRPool() ; + void createAPRPool() ; + +protected: + apr_pool_t* mPool ; //pointing to an apr_pool + apr_pool_t* mParent ; //parent pool + apr_size_t mMaxSize ; //max size of mPool, mPool should return memory to system if allocated memory beyond this limit. However it seems not to work. + apr_status_t mStatus ; //status when creating the pool + BOOL mReleasePoolFlag ; //if set, mPool is destroyed when LLAPRPool is deleted. default value is true. +}; + +// +//volatile LL apr_pool +//which clears memory automatically. +//so it can not hold static data or data after memory is cleared +// +class LL_COMMON_API LLVolatileAPRPool : public LLAPRPool +{ +public: + LLVolatileAPRPool(BOOL is_local = TRUE, apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE); + virtual ~LLVolatileAPRPool(); + + /*virtual*/ apr_pool_t* getAPRPool() ; //define this virtual function to avoid any mistakenly calling LLAPRPool::getAPRPool(). + apr_pool_t* getVolatileAPRPool() ; + void clearVolatileAPRPool() ; + + BOOL isFull() ; + +private: + S32 mNumActiveRef ; //number of active pointers pointing to the apr_pool. + S32 mNumTotalRef ; //number of total pointers pointing to the apr_pool since last creating. + + apr_thread_mutex_t *mMutexp; + apr_pool_t *mMutexPool; +} ; /** * @class LLScopedLock @@ -143,20 +205,15 @@ class LL_COMMON_API LLAPRFile : boost::noncopyable // make this non copyable since a copy closes the file private: apr_file_t* mFile ; - LLVolatileAPRPool* mVolatileFilePoolp; // (Thread local) APR pool currently in use. - LLAPRPool* mRegularFilePoolp; // ...or a regular pool. + LLVolatileAPRPool *mCurrentFilePoolp ; //currently in use apr_pool, could be one of them: sAPRFilePoolp, or a temp pool. public: - enum access_t { - long_lived, // Use a global pool for long-lived file accesses. - short_lived // Use a volatile pool for short-lived file accesses. - }; - LLAPRFile() ; - LLAPRFile(std::string const& filename, apr_int32_t flags, S32* sizep = NULL, access_t access_type = short_lived); + LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL); ~LLAPRFile() ; - - apr_status_t open(const std::string& filename, apr_int32_t flags, access_t access_type, S32* sizep = NULL); + + apr_status_t open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL, S32* sizep = NULL); + apr_status_t open(const std::string& filename, apr_int32_t flags, BOOL use_global_pool); //use gAPRPoolp. apr_status_t close() ; // Returns actual offset, -1 if seek fails @@ -169,24 +226,32 @@ public: apr_file_t* getFileHandle() {return mFile;} +private: + apr_pool_t* getAPRFilePool(apr_pool_t* pool) ; + // //******************************************************************************************************************************* //static components // +public: + static LLVolatileAPRPool *sAPRFilePoolp ; //a global apr_pool for APRFile, which is used only when local pool does not exist. + private: + static apr_file_t* open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags); + static apr_status_t close(apr_file_t* file, LLVolatileAPRPool* pool) ; static S32 seek(apr_file_t* file, apr_seek_where_t where, S32 offset); public: // returns false if failure: - static bool remove(const std::string& filename); - static bool rename(const std::string& filename, const std::string& newname); - static bool isExist(const std::string& filename, apr_int32_t flags = APR_READ); - static S32 size(const std::string& filename); - static bool makeDir(const std::string& dirname); - static bool removeDir(const std::string& dirname); + static bool remove(const std::string& filename, LLVolatileAPRPool* pool = NULL); + static bool rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool = NULL); + static bool isExist(const std::string& filename, LLVolatileAPRPool* pool = NULL, apr_int32_t flags = APR_READ); + static S32 size(const std::string& filename, LLVolatileAPRPool* pool = NULL); + static bool makeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL); + static bool removeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL); // Returns bytes read/written, 0 if read/write fails: - static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes); - static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes); // offset<0 means append + static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); + static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); // offset<0 means append //******************************************************************************************************************************* }; @@ -202,4 +267,6 @@ bool LL_COMMON_API ll_apr_warn_status(apr_status_t status, apr_dso_handle_t* han void LL_COMMON_API ll_apr_assert_status(apr_status_t status); void LL_COMMON_API ll_apr_assert_status(apr_status_t status, apr_dso_handle_t* handle); +extern "C" LL_COMMON_API apr_pool_t* gAPRPoolp; // Global APR memory pool + #endif // LL_LLAPR_H diff --git a/indra/llcommon/llaprpool.cpp b/indra/llcommon/llaprpool.cpp deleted file mode 100644 index 6f21b61b65..0000000000 --- a/indra/llcommon/llaprpool.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/** - * @file llaprpool.cpp - * - * $LicenseInfo:firstyear=2011&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2011, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - * - * CHANGELOG - * and additional copyright holders. - * - * 04/04/2010 - * - Initial version, written by Aleric Inglewood @ SL - * - * 10/11/2010 - * - Added APR_HAS_THREADS #if's to allow creation and destruction - * of subpools by threads other than the parent pool owner. - */ - -#include "linden_common.h" - -#include "llerror.h" -#include "llaprpool.h" -#include "llthread.h" - -// Create a subpool from parent. -void LLAPRPool::create(LLAPRPool& parent) -{ - llassert(!mPool); // Must be non-initialized. - mParent = &parent; - if (!mParent) // Using the default parameter? - { - // By default use the root pool of the current thread. - mParent = &LLThreadLocalData::tldata().mRootPool; - } - llassert(mParent->mPool); // Parent must be initialized. -#if APR_HAS_THREADS - // As per the documentation of APR (ie http://apr.apache.org/docs/apr/1.4/apr__pools_8h.html): - // - // Note that most operations on pools are not thread-safe: a single pool should only be - // accessed by a single thread at any given time. The one exception to this rule is creating - // a subpool of a given pool: one or more threads can safely create subpools at the same - // time that another thread accesses the parent pool. - // - // In other words, it's safe for any thread to create a (sub)pool, independent of who - // owns the parent pool. - mOwner = apr_os_thread_current(); -#else - mOwner = mParent->mOwner; - llassert(apr_os_thread_equal(mOwner, apr_os_thread_current())); -#endif - apr_status_t const apr_pool_create_status = apr_pool_create(&mPool, mParent->mPool); - llassert_always(apr_pool_create_status == APR_SUCCESS); - llassert(mPool); // Initialized. - apr_pool_cleanup_register(mPool, this, &s_plain_cleanup, &apr_pool_cleanup_null); -} - -// Destroy the (sub)pool, if any. -void LLAPRPool::destroy(void) -{ - // Only do anything if we are not already (being) destroyed. - if (mPool) - { -#if !APR_HAS_THREADS - // If we are a root pool, then every thread may destruct us: in that case - // we have to assume that no other thread will use this pool concurrently, - // of course. Otherwise, if we are a subpool, only the thread that owns - // the parent may destruct us, since that is the pool that is still alive, - // possibly being used by others and being altered here. - llassert(!mParent || apr_os_thread_equal(mParent->mOwner, apr_os_thread_current())); -#endif - apr_pool_t* pool = mPool; // The use of apr_pool_t is OK here. - // Temporary store before destroying the pool. - mPool = NULL; // Mark that we are BEING destructed. - apr_pool_cleanup_kill(pool, this, &s_plain_cleanup); - apr_pool_destroy(pool); - } -} - -bool LLAPRPool::parent_is_being_destructed(void) -{ - return mParent && (!mParent->mPool || mParent->parent_is_being_destructed()); -} - -LLAPRInitialization::LLAPRInitialization(void) -{ - static bool apr_initialized = false; - - if (!apr_initialized) - { - apr_initialize(); - } - - apr_initialized = true; -} - -bool LLAPRRootPool::sCountInitialized = false; -apr_uint32_t volatile LLAPRRootPool::sCount; - -apr_thread_mutex_t* gLogMutexp; -apr_thread_mutex_t* gCallStacksLogMutexp; - -LLAPRRootPool::LLAPRRootPool(void) : LLAPRInitialization(), LLAPRPool(0) -{ - // sCountInitialized don't need locking because when we get here there is still only a single thread. - if (!sCountInitialized) - { - // Initialize the logging mutex - apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_UNNESTED, mPool); - apr_thread_mutex_create(&gCallStacksLogMutexp, APR_THREAD_MUTEX_UNNESTED, mPool); - - apr_status_t status = apr_atomic_init(mPool); - llassert_always(status == APR_SUCCESS); - apr_atomic_set32(&sCount, 1); // Set to 1 to account for the global root pool. - sCountInitialized = true; - - // Initialize thread-local APR pool support. - // Because this recursively calls LLAPRRootPool::LLAPRRootPool(void) - // it must be done last, so that sCount is already initialized. - LLThreadLocalData::init(); - } - apr_atomic_inc32(&sCount); -} - -LLAPRRootPool::~LLAPRRootPool() -{ - if (!apr_atomic_dec32(&sCount)) - { - // The last pool was destructed. Cleanup remainder of APR. - LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL; - - if (gLogMutexp) - { - // Clean up the logging mutex - - // All other threads NEED to be done before we clean up APR, so this is okay. - apr_thread_mutex_destroy(gLogMutexp); - gLogMutexp = NULL; - } - if (gCallStacksLogMutexp) - { - // Clean up the logging mutex - - // All other threads NEED to be done before we clean up APR, so this is okay. - apr_thread_mutex_destroy(gCallStacksLogMutexp); - gCallStacksLogMutexp = NULL; - } - - // Must destroy ALL, and therefore this last LLAPRRootPool, before terminating APR. - static_cast<LLAPRRootPool*>(this)->destroy(); - - apr_terminate(); - } -} - -//static -// Return a global root pool that is independent of LLThreadLocalData. -// Normally you should NOT use this. Only use for early initialization -// (before main) and deinitialization (after main). -LLAPRRootPool& LLAPRRootPool::get(void) -{ - static LLAPRRootPool global_APRpool(0); - return global_APRpool; -} - -void LLVolatileAPRPool::clearVolatileAPRPool() -{ - llassert_always(mNumActiveRef > 0); - if (--mNumActiveRef == 0) - { - if (isOld()) - { - destroy(); - mNumTotalRef = 0 ; - } - else - { - // This does not actually free the memory, - // it just allows the pool to re-use this memory for the next allocation. - clear(); - } - } - - // Paranoia check if the pool is jammed. - llassert(mNumTotalRef < (FULL_VOLATILE_APR_POOL << 2)) ; -} diff --git a/indra/llcommon/llaprpool.h b/indra/llcommon/llaprpool.h deleted file mode 100644 index bf4102c584..0000000000 --- a/indra/llcommon/llaprpool.h +++ /dev/null @@ -1,256 +0,0 @@ -/** - * @file llaprpool.h - * @brief Implementation of LLAPRPool - * - * $LicenseInfo:firstyear=2011&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2011, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - * - * CHANGELOG - * and additional copyright holders. - * - * 04/04/2010 - * - Initial version, written by Aleric Inglewood @ SL - * - * 10/11/2010 - * - Added APR_HAS_THREADS #if's to allow creation and destruction - * of subpools by threads other than the parent pool owner. - * - * 05/02/2011 - * - Fixed compilation on windows: Suppress compile warning 4996 - * and include <winsock2.h> before including <ws2tcpip.h>, - * by Merov Linden @ SL. - */ - -#ifndef LL_LLAPRPOOL_H -#define LL_LLAPRPOOL_H - -#ifdef LL_WINDOWS -#pragma warning(push) -#pragma warning(disable:4996) -#include <winsock2.h> -#include <ws2tcpip.h> // Needed before including apr_portable.h -#pragma warning(pop) -#endif - -#include "apr_portable.h" -#include "apr_pools.h" -#include "llerror.h" - -extern void ll_init_apr(); - -/** - * @brief A wrapper around the APR memory pool API. - * - * Usage of this class should be restricted to passing it to libapr-1 function calls that need it. - * - */ -class LL_COMMON_API LLAPRPool -{ -protected: - //! Pointer to the underlaying pool. NULL if not initialized. - apr_pool_t* mPool; // The use of apr_pool_t is OK here. - // This is the wrapped pointer that it is all about! - //! Pointer to the parent pool, if any. Only valid when mPool is non-zero. - LLAPRPool* mParent; - //! The thread that owns this memory pool. Only valid when mPool is non-zero. - apr_os_thread_t mOwner; - -public: - /// Construct an uninitialized (destructed) pool. - LLAPRPool(void) : mPool(NULL) { } - - /// Construct a subpool from an existing pool. - /// This is not a copy-constructor, this class doesn't have one! - LLAPRPool(LLAPRPool& parent) : mPool(NULL) { create(parent); } - - /// Destruct the memory pool (free all of its subpools and allocated memory). - ~LLAPRPool() { destroy(); } - -protected: - /// Create a pool that is allocated from the Operating System. Only used by LLAPRRootPool. - LLAPRPool(int) : mPool(NULL), mParent(NULL), mOwner(apr_os_thread_current()) - { - apr_status_t const apr_pool_create_status = apr_pool_create(&mPool, NULL); - llassert_always(apr_pool_create_status == APR_SUCCESS); - llassert(mPool); - apr_pool_cleanup_register(mPool, this, &s_plain_cleanup, &apr_pool_cleanup_null); - } - -public: - /// Create a subpool from parent. May only be called for an uninitialized/destroyed pool. - /// The default parameter causes the root pool of the current thread to be used. - void create(LLAPRPool& parent = *static_cast<LLAPRPool*>(NULL)); - - /// Destroy the (sub)pool, if any. - void destroy(void); - - // Use some safebool idiom (http://www.artima.com/cppsource/safebool.html) rather than operator bool. - typedef LLAPRPool* const LLAPRPool::* const bool_type; - /// Return true if the pool is initialized. - operator bool_type() const { return mPool ? &LLAPRPool::mParent : 0; } - - /// Painful, but we have to either provide access to this, or wrap - /// every APR function call that needs an apr pool as argument. - /// NEVER destroy a pool that is returned by this function! - apr_pool_t* operator()(void) const // The use of apr_pool_t is OK here. - // This is the accessor for passing the pool to libapr-1 functions. - { - llassert(mPool); - llassert(apr_os_thread_equal(mOwner, apr_os_thread_current())); - return mPool; - } - - /// Free all memory without destructing the pool. - void clear(void) - { - llassert(mPool); - llassert(apr_os_thread_equal(mOwner, apr_os_thread_current())); - apr_pool_clear(mPool); - } - -// These methods would make this class 'complete' (as wrapper around the libapr -// pool functions), but we don't use memory pools in the viewer (only when -// we are forced to pass one to a libapr call), so don't define them in order -// not to encourage people to use them. -#if 0 - void* palloc(size_t size) - { - llassert(mPool); - llassert(apr_os_thread_equal(mOwner, apr_os_thread_current())); - return apr_palloc(mPool, size); - } - void* pcalloc(size_t size) - { - llassert(mPool); - llassert(apr_os_thread_equal(mOwner, apr_os_thread_current())); - return apr_pcalloc(mPool, size); - } -#endif - -private: - bool parent_is_being_destructed(void); - static apr_status_t s_plain_cleanup(void* userdata) { return static_cast<LLAPRPool*>(userdata)->plain_cleanup(); } - - apr_status_t plain_cleanup(void) - { - if (mPool && // We are not being destructed, - parent_is_being_destructed()) // but our parent is. - // This means the pool is being destructed recursively by libapr - // because one of its parents is being destructed. - { - mPool = NULL; // Stop destroy() from destructing the pool again. - } - return APR_SUCCESS; - } -}; - -class LLAPRInitialization -{ -public: - LLAPRInitialization(void); -}; - -/** - * @brief Root memory pool (allocates memory from the operating system). - * - * This class should only be used by LLThreadLocalData - * (and LLMutexRootPool when APR_HAS_THREADS isn't defined). - */ -class LL_COMMON_API LLAPRRootPool : public LLAPRInitialization, public LLAPRPool -{ -private: - /// Construct a root memory pool. Should only be used by LLThreadLocalData and LLMutexRootPool. - friend class LLThreadLocalData; -#if !APR_HAS_THREADS - friend class LLMutexRootPool; -#endif - /// Construct a root memory pool. - /// Should only be used by LLThreadLocalData. - LLAPRRootPool(void); - ~LLAPRRootPool(); - -private: - // Keep track of how many root pools exist and when the last one is destructed. - static bool sCountInitialized; - static apr_uint32_t volatile sCount; - -public: - // Return a global root pool that is independent of LLThreadLocalData. - // Normally you should not use this. Only use for early initialization - // (before main) and deinitialization (after main). - static LLAPRRootPool& get(void); - -#if APR_POOL_DEBUG - void grab_ownership(void) - { - // You need a patched libapr to use this. - // See http://web.archiveorange.com/archive/v/5XO9y2zoxUOMt6Gmi1OI - apr_pool_owner_set(mPool); - } -#endif - -private: - // Used for constructing the Special Global Root Pool (returned by LLAPRRootPool::get). - // It is the same as the default constructor but omits to increment sCount. As a result, - // we must be sure that at least one other LLAPRRootPool is created before termination - // of the application (which is the case: we create one LLAPRRootPool per thread). - LLAPRRootPool(int) : LLAPRInitialization(), LLAPRPool(0) { } -}; - -/** Volatile memory pool - * - * 'Volatile' APR memory pool which normally only clears memory, - * and does not destroy the pool (the same pool is reused) for - * greater efficiency. However, as a safe guard the apr pool - * is destructed every FULL_VOLATILE_APR_POOL uses to allow - * the system memory to be allocated more efficiently and not - * get scattered through RAM. - */ -class LL_COMMON_API LLVolatileAPRPool : protected LLAPRPool -{ -public: - LLVolatileAPRPool(void) : mNumActiveRef(0), mNumTotalRef(0) { } - - void clearVolatileAPRPool(void); - - bool isOld(void) const { return mNumTotalRef > FULL_VOLATILE_APR_POOL; } - bool isUnused() const { return mNumActiveRef == 0; } - -private: - friend class LLScopedVolatileAPRPool; - friend class LLAPRFile; - apr_pool_t* getVolatileAPRPool(void) // The use of apr_pool_t is OK here. - { - if (!mPool) create(); - ++mNumActiveRef; - ++mNumTotalRef; - return LLAPRPool::operator()(); - } - -private: - S32 mNumActiveRef; // Number of active uses of the pool. - S32 mNumTotalRef; // Number of total uses of the pool since last creation. - - // Maximum number of references to LLVolatileAPRPool until the pool is recreated. - static S32 const FULL_VOLATILE_APR_POOL = 1024; -}; - -#endif // LL_LLAPRPOOL_H diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp index b8a7394852..8be9e4f4de 100644 --- a/indra/llcommon/llcommon.cpp +++ b/indra/llcommon/llcommon.cpp @@ -31,9 +31,17 @@ #include "llthread.h" //static +BOOL LLCommon::sAprInitialized = FALSE; + +//static void LLCommon::initClass() { LLMemory::initClass(); + if (!sAprInitialized) + { + ll_init_apr(); + sAprInitialized = TRUE; + } LLTimer::initClass(); LLThreadSafeRefCount::initThreadSafeRefCount(); // LLWorkerThread::initClass(); @@ -47,5 +55,10 @@ void LLCommon::cleanupClass() // LLWorkerThread::cleanupClass(); LLThreadSafeRefCount::cleanupThreadSafeRefCount(); LLTimer::cleanupClass(); + if (sAprInitialized) + { + ll_cleanup_apr(); + sAprInitialized = FALSE; + } LLMemory::cleanupClass(); } diff --git a/indra/llcommon/llcommon.h b/indra/llcommon/llcommon.h index 171590f3d8..ca9cad5d05 100644 --- a/indra/llcommon/llcommon.h +++ b/indra/llcommon/llcommon.h @@ -35,6 +35,8 @@ class LL_COMMON_API LLCommon public: static void initClass(); static void cleanupClass(); +private: + static BOOL sAprInitialized; }; #endif diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index bda9d7c177..c35799bbb9 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -866,9 +866,6 @@ You get: */ -extern apr_thread_mutex_t* gLogMutexp; -extern apr_thread_mutex_t* gCallStacksLogMutexp; - namespace { bool checkLevelMap(const LevelMap& map, const std::string& key, LLError::ELevel& level) diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 369f2a7a97..b3e604f8e8 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -296,4 +296,5 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; Such computation is done iff the message will be logged. */ + #endif // LL_LLERROR_H diff --git a/indra/llcommon/llfixedbuffer.cpp b/indra/llcommon/llfixedbuffer.cpp index 4b5cdbe288..d394f179fb 100644 --- a/indra/llcommon/llfixedbuffer.cpp +++ b/indra/llcommon/llfixedbuffer.cpp @@ -30,7 +30,8 @@ LLFixedBuffer::LLFixedBuffer(const U32 max_lines) : LLLineBuffer(), - mMaxLines(max_lines) + mMaxLines(max_lines), + mMutex(NULL) { mTimer.reset(); } diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index 8c02ad8290..3c5c20d0bf 100644 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -165,33 +165,60 @@ void LLMemory::logMemoryInfo(BOOL update) llinfos << "Current allocated page size (KB): " << sAllocatedPageSizeInKB << llendl ; llinfos << "Current availabe physical memory(KB): " << sAvailPhysicalMemInKB << llendl ; llinfos << "Current max usable memory(KB): " << sMaxPhysicalMemInKB << llendl ; + + llinfos << "--- private pool information -- " << llendl ; + llinfos << "Total reserved (KB): " << LLPrivateMemoryPoolManager::getInstance()->mTotalReservedSize / 1024 << llendl ; + llinfos << "Total allocated (KB): " << LLPrivateMemoryPoolManager::getInstance()->mTotalAllocatedSize / 1024 << llendl ; } //return 0: everything is normal; //return 1: the memory pool is low, but not in danger; //return -1: the memory pool is in danger, is about to crash. //static -S32 LLMemory::isMemoryPoolLow() +bool LLMemory::isMemoryPoolLow() { static const U32 LOW_MEMEOY_POOL_THRESHOLD_KB = 64 * 1024 ; //64 MB for emergency use + const static U32 MAX_SIZE_CHECKED_MEMORY_BLOCK = 64 * 1024 * 1024 ; //64 MB + static void* last_reserved_address = NULL ; if(!sEnableMemoryFailurePrevention) { - return 0 ; //no memory failure prevention. + return false ; //no memory failure prevention. } if(sAvailPhysicalMemInKB < (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2)) //out of physical memory { - return -1 ; + return true ; } if(sAllocatedPageSizeInKB + (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2) > sMaxHeapSizeInKB) //out of virtual address space. { - return -1 ; + return true ; } - return (S32)(sAvailPhysicalMemInKB < LOW_MEMEOY_POOL_THRESHOLD_KB || + bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMEOY_POOL_THRESHOLD_KB || sAllocatedPageSizeInKB + LOW_MEMEOY_POOL_THRESHOLD_KB > sMaxHeapSizeInKB) ; + + //check the virtual address space fragmentation + if(!is_low) + { + if(!last_reserved_address) + { + last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ; + } + else + { + last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ; + if(!last_reserved_address) //failed, try once more + { + last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ; + } + } + + is_low = !last_reserved_address ; //allocation failed + } + + return is_low ; } //static @@ -1289,18 +1316,16 @@ U16 LLPrivateMemoryPool::LLMemoryChunk::getPageLevel(U32 size) //-------------------------------------------------------------------- const U32 CHUNK_SIZE = 4 << 20 ; //4 MB const U32 LARGE_CHUNK_SIZE = 4 * CHUNK_SIZE ; //16 MB -LLPrivateMemoryPool::LLPrivateMemoryPool(S32 type) : +LLPrivateMemoryPool::LLPrivateMemoryPool(S32 type, U32 max_pool_size) : mMutexp(NULL), mReservedPoolSize(0), mHashFactor(1), - mType(type) + mType(type), + mMaxPoolSize(max_pool_size) { - const U32 MAX_POOL_SIZE = 256 * 1024 * 1024 ; //256 MB - - mMaxPoolSize = MAX_POOL_SIZE ; if(type == STATIC_THREADED || type == VOLATILE_THREADED) { - mMutexp = new LLMutex ; + mMutexp = new LLMutex(NULL) ; } for(S32 i = 0 ; i < SUPER_ALLOCATION ; i++) @@ -1362,16 +1387,31 @@ char* LLPrivateMemoryPool::allocate(U32 size) chunk = chunk->mNext ; } } - - chunk = addChunk(chunk_idx) ; - if(chunk) + else { - p = chunk->allocate(size) ; + chunk = addChunk(chunk_idx) ; + if(chunk) + { + p = chunk->allocate(size) ; + } } } unlock() ; + if(!p) //to get memory from the private pool failed, try the heap directly + { + static bool to_log = true ; + + if(to_log) + { + llwarns << "The memory pool overflows, now using heap directly!" << llendl ; + to_log = false ; + } + + return (char*)malloc(size) ; + } + return p ; } @@ -1472,7 +1512,7 @@ void LLPrivateMemoryPool::destroyPool() unlock() ; } -void LLPrivateMemoryPool::checkSize(U32 asked_size) +bool LLPrivateMemoryPool::checkSize(U32 asked_size) { if(mReservedPoolSize + asked_size > mMaxPoolSize) { @@ -1480,8 +1520,12 @@ void LLPrivateMemoryPool::checkSize(U32 asked_size) llinfos << "Total reserved size: " << mReservedPoolSize + asked_size << llendl ; llinfos << "Total_allocated Size: " << getTotalAllocatedSize() << llendl ; - llerrs << "The pool is overflowing..." << llendl ; + //llerrs << "The pool is overflowing..." << llendl ; + + return false ; } + + return true ; } LLPrivateMemoryPool::LLMemoryChunk* LLPrivateMemoryPool::addChunk(S32 chunk_index) @@ -1501,7 +1545,11 @@ LLPrivateMemoryPool::LLMemoryChunk* LLPrivateMemoryPool::addChunk(S32 chunk_inde MAX_SLOT_SIZES[chunk_index], MIN_BLOCK_SIZES[chunk_index], MAX_BLOCK_SIZES[chunk_index]) ; } - checkSize(preferred_size + overhead) ; + if(!checkSize(preferred_size + overhead)) + { + return NULL ; + } + mReservedPoolSize += preferred_size + overhead ; char* buffer = (char*)malloc(preferred_size + overhead) ; @@ -1593,7 +1641,7 @@ LLPrivateMemoryPool::LLMemoryChunk* LLPrivateMemoryPool::findChunk(const char* a void LLPrivateMemoryPool::addToHashTable(LLMemoryChunk* chunk) { - static const U16 HASH_FACTORS[] = {41, 83, 193, 317, 419, 523, 0xFFFF}; + static const U16 HASH_FACTORS[] = {41, 83, 193, 317, 419, 523, 719, 997, 1523, 0xFFFF}; U16 i ; if(mChunkHashList.empty()) @@ -1774,7 +1822,7 @@ void LLPrivateMemoryPool::LLChunkHashElement::remove(LLPrivateMemoryPool::LLMemo //-------------------------------------------------------------------- LLPrivateMemoryPoolManager* LLPrivateMemoryPoolManager::sInstance = NULL ; -LLPrivateMemoryPoolManager::LLPrivateMemoryPoolManager(BOOL enabled) +LLPrivateMemoryPoolManager::LLPrivateMemoryPoolManager(BOOL enabled, U32 max_pool_size) { mPoolList.resize(LLPrivateMemoryPool::MAX_TYPES) ; @@ -1784,6 +1832,9 @@ LLPrivateMemoryPoolManager::LLPrivateMemoryPoolManager(BOOL enabled) } mPrivatePoolEnabled = enabled ; + + const U32 MAX_POOL_SIZE = 256 * 1024 * 1024 ; //256 MB + mMaxPrivatePoolSize = llmax(max_pool_size, MAX_POOL_SIZE) ; } LLPrivateMemoryPoolManager::~LLPrivateMemoryPoolManager() @@ -1826,11 +1877,11 @@ LLPrivateMemoryPoolManager::~LLPrivateMemoryPoolManager() } //static -void LLPrivateMemoryPoolManager::initClass(BOOL enabled) +void LLPrivateMemoryPoolManager::initClass(BOOL enabled, U32 max_pool_size) { llassert_always(!sInstance) ; - sInstance = new LLPrivateMemoryPoolManager(enabled) ; + sInstance = new LLPrivateMemoryPoolManager(enabled, max_pool_size) ; } //static @@ -1862,7 +1913,7 @@ LLPrivateMemoryPool* LLPrivateMemoryPoolManager::newPool(S32 type) if(!mPoolList[type]) { - mPoolList[type] = new LLPrivateMemoryPool(type) ; + mPoolList[type] = new LLPrivateMemoryPool(type, mMaxPrivatePoolSize) ; } return mPoolList[type] ; diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index db753f0d8b..6967edd7e7 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -122,7 +122,7 @@ public: static void initMaxHeapSizeGB(F32 max_heap_size_gb, BOOL prevent_heap_failure); static void updateMemoryInfo() ; static void logMemoryInfo(BOOL update = FALSE); - static S32 isMemoryPoolLow(); + static bool isMemoryPoolLow(); static U32 getAvailableMemKB() ; static U32 getMaxMemKB() ; @@ -303,7 +303,7 @@ public: } ; private: - LLPrivateMemoryPool(S32 type) ; + LLPrivateMemoryPool(S32 type, U32 max_pool_size) ; ~LLPrivateMemoryPool() ; char *allocate(U32 size) ; @@ -320,7 +320,7 @@ private: void unlock() ; S32 getChunkIndex(U32 size) ; LLMemoryChunk* addChunk(S32 chunk_index) ; - void checkSize(U32 asked_size) ; + bool checkSize(U32 asked_size) ; void removeChunk(LLMemoryChunk* chunk) ; U16 findHashKey(const char* addr); void addToHashTable(LLMemoryChunk* chunk) ; @@ -383,12 +383,12 @@ private: class LL_COMMON_API LLPrivateMemoryPoolManager { private: - LLPrivateMemoryPoolManager(BOOL enabled) ; + LLPrivateMemoryPoolManager(BOOL enabled, U32 max_pool_size) ; ~LLPrivateMemoryPoolManager() ; public: static LLPrivateMemoryPoolManager* getInstance() ; - static void initClass(BOOL enabled) ; + static void initClass(BOOL enabled, U32 pool_size) ; static void destroyClass() ; LLPrivateMemoryPool* newPool(S32 type) ; @@ -398,6 +398,7 @@ private: static LLPrivateMemoryPoolManager* sInstance ; std::vector<LLPrivateMemoryPool*> mPoolList ; BOOL mPrivatePoolEnabled; + U32 mMaxPrivatePoolSize; public: //debug and statistics info. diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index efd9c4b68f..5dee7a3541 100644 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -32,7 +32,7 @@ //============================================================================ // MAIN THREAD -LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded) : +LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded, bool should_pause) : LLThread(name), mThreaded(threaded), mIdleThread(TRUE), @@ -41,6 +41,11 @@ LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded) : { if (mThreaded) { + if(should_pause) + { + pause() ; //call this before start the thread. + } + start(); } } diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h index a53b22f6fc..499d13a792 100644 --- a/indra/llcommon/llqueuedthread.h +++ b/indra/llcommon/llqueuedthread.h @@ -149,7 +149,7 @@ public: static handle_t nullHandle() { return handle_t(0); } public: - LLQueuedThread(const std::string& name, bool threaded = true); + LLQueuedThread(const std::string& name, bool threaded = true, bool should_pause = false); virtual ~LLQueuedThread(); virtual void shutdown(); diff --git a/indra/llcommon/llscopedvolatileaprpool.h b/indra/llcommon/llscopedvolatileaprpool.h deleted file mode 100644 index dbaf4edcad..0000000000 --- a/indra/llcommon/llscopedvolatileaprpool.h +++ /dev/null @@ -1,52 +0,0 @@ -/** - * @file llscopedvolatileaprpool.h - * @brief Implementation of LLScopedVolatileAPRPool - * - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2011, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLSCOPEDVOLATILEAPRPOOL_H -#define LL_LLSCOPEDVOLATILEAPRPOOL_H - -#include "llthread.h" - -/** Scoped volatile memory pool. - * - * As the LLVolatileAPRPool should never keep allocations very - * long, its most common use is for allocations with a lifetime - * equal to it's scope. - * - * This is a convenience class that makes just a little easier to type. - */ -class LL_COMMON_API LLScopedVolatileAPRPool -{ -private: - LLVolatileAPRPool& mPool; - apr_pool_t* mScopedAPRpool; // The use of apr_pool_t is OK here. -public: - LLScopedVolatileAPRPool() : mPool(LLThreadLocalData::tldata().mVolatileAPRPool), mScopedAPRpool(mPool.getVolatileAPRPool()) { } - ~LLScopedVolatileAPRPool() { mPool.clearVolatileAPRPool(); } - //! @attention Only use this to pass the underlaying pointer to a libapr-1 function that requires it. - operator apr_pool_t*() const { return mScopedAPRpool; } // The use of apr_pool_t is OK here. -}; - -#endif diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp index bf216d41bf..be9db53906 100644 --- a/indra/llcommon/llsdserialize_xml.cpp +++ b/indra/llcommon/llsdserialize_xml.cpp @@ -354,7 +354,6 @@ static unsigned get_till_eol(std::istream& input, char *buf, unsigned bufsize) return count; } -LLFastTimer::DeclareTimer FTM_SD_PARSE_READ_STREAM("LLSD Read Stream"); S32 LLSDXMLParser::Impl::parse(std::istream& input, LLSD& data) { XML_Status status; @@ -374,7 +373,7 @@ S32 LLSDXMLParser::Impl::parse(std::istream& input, LLSD& data) { break; } - { LLFastTimer _(FTM_SD_PARSE_READ_STREAM); + { count = get_till_eol(input, (char *)buffer, BUFFER_SIZE); if (!count) diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index bdde1b5c48..4063cc730b 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -36,12 +36,6 @@ #include <sched.h> #endif -#if !LL_DARWIN -U32 ll_thread_local local_thread_ID = 0; -#endif - -U32 LLThread::sIDIter = 0; - //---------------------------------------------------------------------------- // Usage: // void run_func(LLThread* thread) @@ -62,6 +56,12 @@ U32 LLThread::sIDIter = 0; // //---------------------------------------------------------------------------- +#if !LL_DARWIN +U32 ll_thread_local sThreadID = 0; +#endif + +U32 LLThread::sIDIter = 0; + LL_COMMON_API void assert_main_thread() { static U32 s_thread_id = LLThread::currentID(); @@ -79,12 +79,9 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap LLThread *threadp = (LLThread *)datap; #if !LL_DARWIN - local_thread_ID = threadp->mID; + sThreadID = threadp->mID; #endif - // Create a thread local data. - LLThreadLocalData::create(threadp); - // Run the user supplied function threadp->run(); @@ -97,22 +94,40 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap } -LLThread::LLThread(std::string const& name) : - mPaused(false), +LLThread::LLThread(const std::string& name, apr_pool_t *poolp) : + mPaused(FALSE), mName(name), mAPRThreadp(NULL), - mStatus(STOPPED), - mThreadLocalData(NULL) + mStatus(STOPPED) { - mID = ++sIDIter; //flaw: assume this is called only in the main thread! + mID = ++sIDIter; - mRunCondition = new LLCondition; + // 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); + + mLocalAPRFilePoolp = NULL ; } LLThread::~LLThread() { shutdown(); + + if(mLocalAPRFilePoolp) + { + delete mLocalAPRFilePoolp ; + mLocalAPRFilePoolp = NULL ; + } } void LLThread::shutdown() @@ -149,7 +164,7 @@ void LLThread::shutdown() if (!isStopped()) { // This thread just wouldn't stop, even though we gave it time - //llwarns << "LLThread::shutdown() exiting thread before clean exit!" << llendl; + //llwarns << "LLThread::~LLThread() exiting thread before clean exit!" << llendl; // Put a stake in its heart. apr_thread_exit(mAPRThreadp, -1); return; @@ -159,8 +174,15 @@ void LLThread::shutdown() delete mRunCondition; mRunCondition = 0; + + if (mIsLocalPool && mAPRPoolp) + { + apr_pool_destroy(mAPRPoolp); + mAPRPoolp = 0; + } } + void LLThread::start() { llassert(isStopped()); @@ -169,7 +191,7 @@ void LLThread::start() mStatus = RUNNING; apr_status_t status = - apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, tldata().mRootPool()); + apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp); if(status == APR_SUCCESS) { @@ -194,7 +216,7 @@ void LLThread::pause() if (!mPaused) { // this will cause the thread to stop execution as soon as checkPause() is called - mPaused = true; // Does not need to be atomic since this is only set/unset from the main thread + mPaused = 1; // Does not need to be atomic since this is only set/unset from the main thread } } @@ -202,7 +224,7 @@ void LLThread::unpause() { if (mPaused) { - mPaused = false; + mPaused = 0; } wake(); // wake up the thread if necessary @@ -279,76 +301,116 @@ void LLThread::wakeLocked() } } -#ifdef SHOW_ASSERT -// This allows the use of llassert(is_main_thread()) to assure the current thread is the main thread. -static apr_os_thread_t main_thread_id; -LL_COMMON_API bool is_main_thread(void) { return apr_os_thread_equal(main_thread_id, apr_os_thread_current()); } -#endif - -// The thread private handle to access the LLThreadLocalData instance. -apr_threadkey_t* LLThreadLocalData::sThreadLocalDataKey; +//============================================================================ -//static -void LLThreadLocalData::init(void) +LLMutex::LLMutex(apr_pool_t *poolp) : + mAPRMutexp(NULL), mCount(0), mLockingThread(NO_THREAD) { - // Only do this once. - if (sThreadLocalDataKey) + //if (poolp) + //{ + // mIsLocalPool = FALSE; + // mAPRPoolp = poolp; + //} + //else { - return; + mIsLocalPool = TRUE; + apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread } + apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp); +} - apr_status_t status = apr_threadkey_private_create(&sThreadLocalDataKey, &LLThreadLocalData::destroy, LLAPRRootPool::get()()); - ll_apr_assert_status(status); // Or out of memory, or system-imposed limit on the - // total number of keys per process {PTHREAD_KEYS_MAX} - // has been exceeded. - - // Create the thread-local data for the main thread (this function is called by the main thread). - LLThreadLocalData::create(NULL); -#ifdef SHOW_ASSERT - // This function is called by the main thread. - main_thread_id = apr_os_thread_current(); +LLMutex::~LLMutex() +{ +#if MUTEX_DEBUG + //bad assertion, the subclass LLSignal might be "locked", and that's OK + //llassert_always(!isLocked()); // better not be locked! #endif + apr_thread_mutex_destroy(mAPRMutexp); + mAPRMutexp = NULL; + if (mIsLocalPool) + { + apr_pool_destroy(mAPRPoolp); + } } -// This is called once for every thread when the thread is destructed. -//static -void LLThreadLocalData::destroy(void* thread_local_data) + +void LLMutex::lock() { - delete static_cast<LLThreadLocalData*>(thread_local_data); +#if LL_DARWIN + if (mLockingThread == LLThread::currentID()) +#else + if (mLockingThread == sThreadID) +#endif + { //redundant lock + mCount++; + return; + } + + apr_thread_mutex_lock(mAPRMutexp); + +#if MUTEX_DEBUG + // Have to have the lock before we can access the debug info + U32 id = LLThread::currentID(); + if (mIsLocked[id] != FALSE) + llerrs << "Already locked in Thread: " << id << llendl; + mIsLocked[id] = TRUE; +#endif + +#if LL_DARWIN + mLockingThread = LLThread::currentID(); +#else + mLockingThread = sThreadID; +#endif } -//static -void LLThreadLocalData::create(LLThread* threadp) +void LLMutex::unlock() { - LLThreadLocalData* new_tld = new LLThreadLocalData; - if (threadp) - { - threadp->mThreadLocalData = new_tld; + if (mCount > 0) + { //not the root unlock + mCount--; + return; } - apr_status_t status = apr_threadkey_private_set(new_tld, sThreadLocalDataKey); - llassert_always(status == APR_SUCCESS); + +#if MUTEX_DEBUG + // Access the debug info while we have the lock + U32 id = LLThread::currentID(); + if (mIsLocked[id] != TRUE) + llerrs << "Not locked in Thread: " << id << llendl; + mIsLocked[id] = FALSE; +#endif + + mLockingThread = NO_THREAD; + apr_thread_mutex_unlock(mAPRMutexp); } -//static -LLThreadLocalData& LLThreadLocalData::tldata(void) +bool LLMutex::isLocked() { - if (!sThreadLocalDataKey) + apr_status_t status = apr_thread_mutex_trylock(mAPRMutexp); + if (APR_STATUS_IS_EBUSY(status)) { - LLThreadLocalData::init(); + return true; } + else + { + apr_thread_mutex_unlock(mAPRMutexp); + return false; + } +} - void* data; - apr_status_t status = apr_threadkey_private_get(&data, sThreadLocalDataKey); - llassert_always(status == APR_SUCCESS); - return *static_cast<LLThreadLocalData*>(data); +U32 LLMutex::lockingThread() const +{ + return mLockingThread; } //============================================================================ -LLCondition::LLCondition(LLAPRPool& parent) : LLMutex(parent) +LLCondition::LLCondition(apr_pool_t *poolp) : + LLMutex(poolp) { - apr_thread_cond_create(&mAPRCondp, mPool()); + // base class (LLMutex) has already ensured that mAPRPoolp is set up. + + apr_thread_cond_create(&mAPRCondp, mAPRPoolp); } @@ -361,6 +423,15 @@ LLCondition::~LLCondition() void LLCondition::wait() { + if (!isLocked()) + { //mAPRMutexp MUST be locked before calling apr_thread_cond_wait + apr_thread_mutex_lock(mAPRMutexp); +#if MUTEX_DEBUG + // avoid asserts on destruction in non-release builds + U32 id = LLThread::currentID(); + mIsLocked[id] = TRUE; +#endif + } apr_thread_cond_wait(mAPRCondp, mAPRMutexp); } @@ -375,44 +446,6 @@ void LLCondition::broadcast() } //============================================================================ -LLMutexBase::LLMutexBase() : - mLockingThread(NO_THREAD), - mCount(0) -{ -} - -void LLMutexBase::lock() -{ -#if LL_DARWIN - if (mLockingThread == LLThread::currentID()) -#else - if (mLockingThread == local_thread_ID) -#endif - { //redundant lock - mCount++; - return; - } - - apr_thread_mutex_lock(mAPRMutexp); - -#if LL_DARWIN - mLockingThread = LLThread::currentID(); -#else - mLockingThread = local_thread_ID; -#endif -} - -void LLMutexBase::unlock() -{ - if (mCount > 0) - { //not the root unlock - mCount--; - return; - } - mLockingThread = NO_THREAD; - - apr_thread_mutex_unlock(mAPRMutexp); -} //---------------------------------------------------------------------------- @@ -424,7 +457,7 @@ void LLThreadSafeRefCount::initThreadSafeRefCount() { if (!sMutex) { - sMutex = new LLMutex; + sMutex = new LLMutex(0); } } diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index b631b96252..40291a2569 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -29,13 +29,7 @@ #include "llapp.h" #include "llapr.h" -#include "llmemory.h" #include "apr_thread_cond.h" -#include "llaprpool.h" - -#ifdef SHOW_ASSERT -extern LL_COMMON_API bool is_main_thread(void); -#endif class LLThread; class LLMutex; @@ -47,22 +41,6 @@ class LLCondition; #define ll_thread_local __thread #endif -class LL_COMMON_API LLThreadLocalData -{ -private: - static apr_threadkey_t* sThreadLocalDataKey; - -public: - // Thread-local memory pools. - LLAPRRootPool mRootPool; - LLVolatileAPRPool mVolatileAPRPool; - - static void init(void); - static void destroy(void* thread_local_data); - static void create(LLThread* pthread); - static LLThreadLocalData& tldata(void); -}; - class LL_COMMON_API LLThread { private: @@ -76,7 +54,7 @@ public: QUITTING= 2 // Someone wants this thread to quit } EThreadStatus; - LLThread(std::string const& name); + 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 @@ -91,7 +69,7 @@ public: // Called from MAIN THREAD. void pause(); void unpause(); - bool isPaused() { return isStopped() || mPaused; } + bool isPaused() { return isStopped() || mPaused == TRUE; } // Cause the thread to wake up and check its condition void wake(); @@ -105,11 +83,13 @@ public: // this kicks off the apr thread void start(void); - // Return thread-local data for the current thread. - static LLThreadLocalData& tldata(void) { return LLThreadLocalData::tldata(); } + apr_pool_t *getAPRPool() { return mAPRPoolp; } + LLVolatileAPRPool* getLocalAPRFilePool() { return mLocalAPRFilePoolp ; } + + U32 getID() const { return mID; } private: - bool mPaused; + BOOL mPaused; // static function passed to APR thread creation routine static void *APR_THREAD_FUNC staticRun(apr_thread_t *apr_threadp, void *datap); @@ -119,11 +99,15 @@ protected: LLCondition* mRunCondition; apr_thread_t *mAPRThreadp; + apr_pool_t *mAPRPoolp; + BOOL mIsLocalPool; EThreadStatus mStatus; U32 mID; - - friend void LLThreadLocalData::create(LLThread* threadp); - LLThreadLocalData* mThreadLocalData; + + //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(); @@ -153,15 +137,7 @@ protected: #define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO) -#ifdef MUTEX_DEBUG -// We really shouldn't be using recursive locks. Make sure of that in debug mode. -#define MUTEX_FLAG APR_THREAD_MUTEX_UNNESTED -#else -// Use the fastest platform-optimal lock behavior (can be recursive or non-recursive). -#define MUTEX_FLAG APR_THREAD_MUTEX_DEFAULT -#endif - -class LL_COMMON_API LLMutexBase +class LL_COMMON_API LLMutex { public: typedef enum @@ -169,74 +145,32 @@ public: NO_THREAD = 0xFFFFFFFF } e_locking_thread; - LLMutexBase() ; - - void lock() ; - void unlock() ; - // Returns true if lock was obtained successfully. - bool trylock() { return !APR_STATUS_IS_EBUSY(apr_thread_mutex_trylock(mAPRMutexp)); } - - // non-blocking, but does do a lock/unlock so not free - bool isLocked() { bool is_not_locked = trylock(); if (is_not_locked) unlock(); return !is_not_locked; } - + LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex + virtual ~LLMutex(); + + void lock(); // blocks + void unlock(); + bool isLocked(); // non-blocking, but does do a lock/unlock so not free + U32 lockingThread() const; //get ID of locking thread + protected: - // mAPRMutexp is initialized and uninitialized in the derived class. - apr_thread_mutex_t* mAPRMutexp; + apr_thread_mutex_t *mAPRMutexp; mutable U32 mCount; mutable U32 mLockingThread; -}; - -class LL_COMMON_API LLMutex : public LLMutexBase -{ -public: - LLMutex(LLAPRPool& parent = LLThread::tldata().mRootPool) : mPool(parent) - { - apr_thread_mutex_create(&mAPRMutexp, MUTEX_FLAG, mPool()); - } - ~LLMutex() - { - //this assertion erroneously triggers whenever an LLCondition is destroyed - //llassert(!isLocked()); // better not be locked! - apr_thread_mutex_destroy(mAPRMutexp); - mAPRMutexp = NULL; - } - -protected: - LLAPRPool mPool; -}; - -#if APR_HAS_THREADS -// No need to use a root pool in this case. -typedef LLMutex LLMutexRootPool; -#else // APR_HAS_THREADS -class LL_COMMON_API LLMutexRootPool : public LLMutexBase -{ -public: - LLMutexRootPool(void) - { - apr_thread_mutex_create(&mAPRMutexp, MUTEX_FLAG, mRootPool()); - } - ~LLMutexRootPool() - { -#if APR_POOL_DEBUG - // It is allowed to destruct root pools from a different thread. - mRootPool.grab_ownership(); + + apr_pool_t *mAPRPoolp; + BOOL mIsLocalPool; + +#if MUTEX_DEBUG + std::map<U32, BOOL> mIsLocked; #endif - llassert(!isLocked()); - apr_thread_mutex_destroy(mAPRMutexp); - mAPRMutexp = NULL; - } - -protected: - LLAPRRootPool mRootPool; }; -#endif // APR_HAS_THREADS // Actually a condition/mutex pair (since each condition needs to be associated with a mutex). class LL_COMMON_API LLCondition : public LLMutex { public: - LLCondition(LLAPRPool& parent = LLThread::tldata().mRootPool); + LLCondition(apr_pool_t *apr_poolp); // Defaults to global pool, could use the thread pool as well. ~LLCondition(); void wait(); // blocks @@ -247,10 +181,10 @@ protected: apr_thread_cond_t *mAPRCondp; }; -class LL_COMMON_API LLMutexLock +class LLMutexLock { public: - LLMutexLock(LLMutexBase* mutex) + LLMutexLock(LLMutex* mutex) { mMutex = mutex; mMutex->lock(); @@ -260,7 +194,7 @@ public: mMutex->unlock(); } private: - LLMutexBase* mMutex; + LLMutex* mMutex; }; //============================================================================ diff --git a/indra/llcommon/llthreadsafequeue.cpp b/indra/llcommon/llthreadsafequeue.cpp index 05d24944f3..8a73e632a9 100644 --- a/indra/llcommon/llthreadsafequeue.cpp +++ b/indra/llcommon/llthreadsafequeue.cpp @@ -34,11 +34,19 @@ //----------------------------------------------------------------------------- -LLThreadSafeQueueImplementation::LLThreadSafeQueueImplementation(unsigned int capacity): +LLThreadSafeQueueImplementation::LLThreadSafeQueueImplementation(apr_pool_t * pool, unsigned int capacity): + mOwnsPool(pool == 0), + mPool(pool), mQueue(0) { - mPool.create(); - apr_status_t status = apr_queue_create(&mQueue, capacity, mPool()); + if(mOwnsPool) { + apr_status_t status = apr_pool_create(&mPool, 0); + if(status != APR_SUCCESS) throw LLThreadSafeQueueError("failed to allocate pool"); + } else { + ; // No op. + } + + apr_status_t status = apr_queue_create(&mQueue, capacity, mPool); if(status != APR_SUCCESS) throw LLThreadSafeQueueError("failed to allocate queue"); } @@ -51,6 +59,7 @@ LLThreadSafeQueueImplementation::~LLThreadSafeQueueImplementation() " elements;" << "memory will be leaked" << LL_ENDL; apr_queue_term(mQueue); } + if(mOwnsPool && (mPool != 0)) apr_pool_destroy(mPool); } diff --git a/indra/llcommon/llthreadsafequeue.h b/indra/llcommon/llthreadsafequeue.h index 43d0b396f2..58cac38769 100644 --- a/indra/llcommon/llthreadsafequeue.h +++ b/indra/llcommon/llthreadsafequeue.h @@ -30,9 +30,9 @@ #include <string> #include <stdexcept> -#include "llaprpool.h" +struct apr_pool_t; // From apr_pools.h class LLThreadSafeQueueImplementation; // See below. @@ -75,7 +75,7 @@ struct apr_queue_t; // From apr_queue.h class LL_COMMON_API LLThreadSafeQueueImplementation { public: - LLThreadSafeQueueImplementation(unsigned int capacity); + LLThreadSafeQueueImplementation(apr_pool_t * pool, unsigned int capacity); ~LLThreadSafeQueueImplementation(); void pushFront(void * element); bool tryPushFront(void * element); @@ -84,7 +84,8 @@ public: size_t size(); private: - LLAPRPool mPool; // The pool used for mQueue. + bool mOwnsPool; + apr_pool_t * mPool; apr_queue_t * mQueue; }; @@ -98,8 +99,9 @@ class LLThreadSafeQueue public: typedef ElementT value_type; - // Constructor. - LLThreadSafeQueue(unsigned int capacity = 1024); + // If the pool is set to NULL one will be allocated and managed by this + // queue. + LLThreadSafeQueue(apr_pool_t * pool = 0, unsigned int capacity = 1024); // Add an element to the front of queue (will block if the queue has // reached capacity). @@ -137,8 +139,8 @@ private: template<typename ElementT> -LLThreadSafeQueue<ElementT>::LLThreadSafeQueue(unsigned int capacity) : - mImplementation(capacity) +LLThreadSafeQueue<ElementT>::LLThreadSafeQueue(apr_pool_t * pool, unsigned int capacity): + mImplementation(pool, capacity) { ; // No op. } diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp index 6b308bb917..4988bdf570 100644 --- a/indra/llcommon/llworkerthread.cpp +++ b/indra/llcommon/llworkerthread.cpp @@ -34,10 +34,15 @@ //============================================================================ // Run on MAIN thread -LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded) : - LLQueuedThread(name, threaded) +LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded, bool should_pause) : + LLQueuedThread(name, threaded, should_pause) { - mDeleteMutex = new LLMutex; + mDeleteMutex = new LLMutex(NULL); + + if(!mLocalAPRFilePoolp) + { + mLocalAPRFilePoolp = new LLVolatileAPRPool() ; + } } LLWorkerThread::~LLWorkerThread() @@ -199,6 +204,7 @@ LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& na mWorkerClassName(name), mRequestHandle(LLWorkerThread::nullHandle()), mRequestPriority(LLWorkerThread::PRIORITY_NORMAL), + mMutex(NULL), mWorkFlags(0) { if (!mWorkerThread) diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h index bef5ef53fe..78a4781d15 100644 --- a/indra/llcommon/llworkerthread.h +++ b/indra/llcommon/llworkerthread.h @@ -83,7 +83,7 @@ private: LLMutex* mDeleteMutex; public: - LLWorkerThread(const std::string& name, bool threaded = true); + LLWorkerThread(const std::string& name, bool threaded = true, bool should_pause = false); ~LLWorkerThread(); /*virtual*/ S32 update(U32 max_time_ms); @@ -94,6 +94,7 @@ public: private: void deleteWorker(LLWorkerClass* workerclass); // schedule for deletion + }; //============================================================================ @@ -193,7 +194,7 @@ protected: U32 mRequestPriority; // last priority set private: - LLMutexRootPool mMutex; // Use LLMutexRootPool since this object is created and destructed by multiple threads. + LLMutex mMutex; LLAtomicU32 mWorkFlags; }; diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index 514ef6011f..331a1692ee 100644 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -414,7 +414,8 @@ bool LLCrashLogger::init() return false; } - gServicePump = new LLPumpIO; + gServicePump = new LLPumpIO(gAPRPoolp); + gServicePump->prime(gAPRPoolp); LLHTTPClient::setPump(*gServicePump); //If we've opened the crash logger, assume we can delete the marker file if it exists diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 23adbf68c8..c239e3df88 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -53,7 +53,7 @@ LLPrivateMemoryPool* LLImageBase::sPrivatePoolp = NULL ; //static void LLImage::initClass() { - sMutex = new LLMutex; + sMutex = new LLMutex(NULL); LLImageBase::createPrivatePool() ; } @@ -1566,7 +1566,8 @@ BOOL LLImageFormatted::load(const std::string &filename) resetLastError(); S32 file_size = 0; - LLAPRFile infile(filename, LL_APR_RB, &file_size); + LLAPRFile infile ; + infile.open(filename, LL_APR_RB, NULL, &file_size); apr_file_t* apr_file = infile.getFileHandle(); if (!apr_file) { @@ -1601,7 +1602,8 @@ BOOL LLImageFormatted::save(const std::string &filename) { resetLastError(); - LLAPRFile outfile(filename, LL_APR_WB); + LLAPRFile outfile ; + outfile.open(filename, LL_APR_WB); if (!outfile.getFileHandle()) { setLastError("Unable to open file for writing", filename); diff --git a/indra/llimage/llimagedimensionsinfo.cpp b/indra/llimage/llimagedimensionsinfo.cpp index 926c749145..c6bfa50b40 100644 --- a/indra/llimage/llimagedimensionsinfo.cpp +++ b/indra/llimage/llimagedimensionsinfo.cpp @@ -40,7 +40,7 @@ bool LLImageDimensionsInfo::load(const std::string& src_filename,U32 codec) mSrcFilename = src_filename; S32 file_size = 0; - apr_status_t s = mInfile.open(src_filename, LL_APR_RB, LLAPRFile::long_lived, &file_size); + apr_status_t s = mInfile.open(src_filename, LL_APR_RB, NULL, &file_size); if (s != APR_SUCCESS) { diff --git a/indra/llimage/llimagedxt.cpp b/indra/llimage/llimagedxt.cpp index 2867f5e6f0..34c6793522 100644 --- a/indra/llimage/llimagedxt.cpp +++ b/indra/llimage/llimagedxt.cpp @@ -26,6 +26,7 @@ #include "linden_common.h" #include "llimagedxt.h" +#include "llmemory.h" //static void LLImageDXT::checkMinWidthHeight(EFileFormat format, S32& width, S32& height) diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index 8c5dc63e9d..cc8cb66d73 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -29,6 +29,7 @@ #include "llmemtype.h" #include "lltimer.h" #include "llmath.h" +#include "llmemory.h" typedef LLImageJ2CImpl* (*CreateLLImageJ2CFunction)(); typedef void (*DestroyLLImageJ2CFunction)(LLImageJ2CImpl*); @@ -370,7 +371,8 @@ BOOL LLImageJ2C::loadAndValidate(const std::string &filename) resetLastError(); S32 file_size = 0; - LLAPRFile infile(filename, LL_APR_RB, &file_size); + LLAPRFile infile ; + infile.open(filename, LL_APR_RB, NULL, &file_size); apr_file_t* apr_file = infile.getFileHandle() ; if (!apr_file) { diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp index 2c6d6f31ea..28dc3bd313 100644 --- a/indra/llimage/llimageworker.cpp +++ b/indra/llimage/llimageworker.cpp @@ -35,18 +35,20 @@ LLImageDecodeThread::LLImageDecodeThread(bool threaded) : LLQueuedThread("imagedecode", threaded) { + mCreationMutex = new LLMutex(getAPRPool()); } //virtual LLImageDecodeThread::~LLImageDecodeThread() { + delete mCreationMutex ; } // MAIN THREAD // virtual S32 LLImageDecodeThread::update(U32 max_time_ms) { - LLMutexLock lock(&mCreationMutex); + LLMutexLock lock(mCreationMutex); for (creation_list_t::iterator iter = mCreationList.begin(); iter != mCreationList.end(); ++iter) { @@ -69,7 +71,7 @@ S32 LLImageDecodeThread::update(U32 max_time_ms) LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* image, U32 priority, S32 discard, BOOL needs_aux, Responder* responder) { - LLMutexLock lock(&mCreationMutex); + LLMutexLock lock(mCreationMutex); handle_t handle = generateHandle(); mCreationList.push_back(creation_info(handle, image, priority, discard, needs_aux, responder)); return handle; @@ -79,7 +81,7 @@ LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* // Returns the size of the mutex guarded list as an indication of sanity S32 LLImageDecodeThread::tut_size() { - LLMutexLock lock(&mCreationMutex); + LLMutexLock lock(mCreationMutex); S32 res = mCreationList.size(); return res; } diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h index 6a24b7522a..c684222fa5 100644 --- a/indra/llimage/llimageworker.h +++ b/indra/llimage/llimageworker.h @@ -98,7 +98,7 @@ private: }; typedef std::list<creation_info> creation_list_t; creation_list_t mCreationList; - LLMutex mCreationMutex; + LLMutex* mCreationMutex; }; #endif diff --git a/indra/llmath/llvolumemgr.cpp b/indra/llmath/llvolumemgr.cpp index 42180197fe..c60b750088 100644 --- a/indra/llmath/llvolumemgr.cpp +++ b/indra/llmath/llvolumemgr.cpp @@ -49,7 +49,7 @@ LLVolumeMgr::LLVolumeMgr() { // the LLMutex magic interferes with easy unit testing, // so you now must manually call useMutex() to use it - //mDataMutex = new LLMutex; + //mDataMutex = new LLMutex(gAPRPoolp); } LLVolumeMgr::~LLVolumeMgr() @@ -216,7 +216,7 @@ void LLVolumeMgr::useMutex() { if (!mDataMutex) { - mDataMutex = new LLMutex; + mDataMutex = new LLMutex(gAPRPoolp); } } diff --git a/indra/llmessage/llares.cpp b/indra/llmessage/llares.cpp index fab9858b69..5a67035ed1 100644 --- a/indra/llmessage/llares.cpp +++ b/indra/llmessage/llares.cpp @@ -28,7 +28,6 @@ #include "linden_common.h" #include "llares.h" -#include "llscopedvolatileaprpool.h" #include <ares_dns.h> #include <ares_version.h> @@ -465,6 +464,11 @@ void LLAres::search(const std::string &query, LLResType type, bool LLAres::process(U64 timeout) { + if (!gAPRPoolp) + { + ll_init_apr(); + } + ares_socket_t socks[ARES_GETSOCK_MAXNUM]; apr_pollfd_t aprFds[ARES_GETSOCK_MAXNUM]; apr_int32_t nsds = 0; @@ -478,7 +482,10 @@ bool LLAres::process(U64 timeout) return nsds > 0; } - LLScopedVolatileAPRPool scoped_pool; + apr_status_t status; + LLAPRPool pool; + status = pool.getStatus() ; + ll_apr_assert_status(status); for (int i = 0; i < ARES_GETSOCK_MAXNUM; i++) { @@ -495,7 +502,7 @@ bool LLAres::process(U64 timeout) apr_socket_t *aprSock = NULL; - apr_status_t status = apr_os_sock_put(&aprSock, (apr_os_sock_t *) &socks[i], scoped_pool); + status = apr_os_sock_put(&aprSock, (apr_os_sock_t *) &socks[i], pool.getAPRPool()); if (status != APR_SUCCESS) { ll_apr_warn_status(status); @@ -504,7 +511,7 @@ bool LLAres::process(U64 timeout) aprFds[nactive].desc.s = aprSock; aprFds[nactive].desc_type = APR_POLL_SOCKET; - aprFds[nactive].p = scoped_pool; + aprFds[nactive].p = pool.getAPRPool(); aprFds[nactive].rtnevents = 0; aprFds[nactive].client_data = &socks[i]; @@ -513,7 +520,7 @@ bool LLAres::process(U64 timeout) if (nactive > 0) { - apr_status_t status = apr_poll(aprFds, nactive, &nsds, timeout); + status = apr_poll(aprFds, nactive, &nsds, timeout); if (status != APR_SUCCESS && status != APR_TIMEUP) { diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 6d9213f51b..330028c926 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -531,7 +531,7 @@ LLCurl::Multi::Multi() mThreaded = LLCurl::sMultiThreaded && LLThread::currentID() == sMainThreadID; if (mThreaded) { - mSignal = new LLCondition(); + mSignal = new LLCondition(NULL); } else { @@ -1189,14 +1189,14 @@ void LLCurl::initClass(bool multi_threaded) check_curl_code(code); - Easy::sHandleMutex = new LLMutex(); - Easy::sMultiMutex = new LLMutex(); + Easy::sHandleMutex = new LLMutex(NULL); + Easy::sMultiMutex = new LLMutex(NULL); #if SAFE_SSL S32 mutex_count = CRYPTO_num_locks(); for (S32 i=0; i<mutex_count; i++) { - sSSLMutex.push_back(new LLMutex); + sSSLMutex.push_back(new LLMutex(NULL)); } CRYPTO_set_id_callback(&LLCurl::ssl_thread_id); CRYPTO_set_locking_callback(&LLCurl::ssl_locking_callback); diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp index 920a57ab55..73e8a69085 100644 --- a/indra/llmessage/lliohttpserver.cpp +++ b/indra/llmessage/lliohttpserver.cpp @@ -963,9 +963,13 @@ private: // static -LLHTTPNode& LLIOHTTPServer::create(LLPumpIO& pump, U16 port) +LLHTTPNode& LLIOHTTPServer::create( + apr_pool_t* pool, LLPumpIO& pump, U16 port) { - LLSocket::ptr_t socket = LLSocket::create(LLSocket::STREAM_TCP, port); + LLSocket::ptr_t socket = LLSocket::create( + pool, + LLSocket::STREAM_TCP, + port); if(!socket) { llerrs << "Unable to initialize socket" << llendl; @@ -974,7 +978,7 @@ LLHTTPNode& LLIOHTTPServer::create(LLPumpIO& pump, U16 port) LLHTTPResponseFactory* factory = new LLHTTPResponseFactory; boost::shared_ptr<LLChainIOFactory> factory_ptr(factory); - LLIOServerSocket* server = new LLIOServerSocket(socket, factory_ptr); + LLIOServerSocket* server = new LLIOServerSocket(pool, socket, factory_ptr); LLPumpIO::chain_t chain; chain.push_back(LLIOPipe::ptr_t(server)); diff --git a/indra/llmessage/lliohttpserver.h b/indra/llmessage/lliohttpserver.h index 2294e4b8ae..5c1b0531ff 100644 --- a/indra/llmessage/lliohttpserver.h +++ b/indra/llmessage/lliohttpserver.h @@ -50,7 +50,7 @@ class LLIOHTTPServer public: typedef void (*timing_callback_t)(const char* hashed_name, F32 time, void* data); - static LLHTTPNode& create(LLPumpIO& pump, U16 port); + static LLHTTPNode& create(apr_pool_t* pool, LLPumpIO& pump, U16 port); /**< Creates an HTTP wire server on the pump for the given TCP port. * * Returns the root node of the new server. Add LLHTTPNode instances diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp index a885ba8ee1..54ceab3422 100644 --- a/indra/llmessage/lliosocket.cpp +++ b/indra/llmessage/lliosocket.cpp @@ -35,7 +35,6 @@ #include "llhost.h" #include "llmemtype.h" #include "llpumpio.h" -#include "llthread.h" // // constants @@ -99,31 +98,51 @@ void ll_debug_socket(const char* msg, apr_socket_t* apr_sock) /// // static -LLSocket::ptr_t LLSocket::create(EType type, U16 port) +LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port) { LLMemType m1(LLMemType::MTYPE_IO_TCP); + LLSocket::ptr_t rv; + apr_socket_t* socket = NULL; + apr_pool_t* new_pool = NULL; apr_status_t status = APR_EGENERAL; - LLSocket::ptr_t rv(new LLSocket); + + // create a pool for the socket + status = apr_pool_create(&new_pool, pool); + if(ll_apr_warn_status(status)) + { + if(new_pool) apr_pool_destroy(new_pool); + return rv; + } if(STREAM_TCP == type) { - status = apr_socket_create(&rv->mSocket, APR_INET, SOCK_STREAM, APR_PROTO_TCP, rv->mPool()); + status = apr_socket_create( + &socket, + APR_INET, + SOCK_STREAM, + APR_PROTO_TCP, + new_pool); } else if(DATAGRAM_UDP == type) { - status = apr_socket_create(&rv->mSocket, APR_INET, SOCK_DGRAM, APR_PROTO_UDP, rv->mPool()); + status = apr_socket_create( + &socket, + APR_INET, + SOCK_DGRAM, + APR_PROTO_UDP, + new_pool); } else { - rv.reset(); + if(new_pool) apr_pool_destroy(new_pool); return rv; } if(ll_apr_warn_status(status)) { - rv->mSocket = NULL; - rv.reset(); + if(new_pool) apr_pool_destroy(new_pool); return rv; } + rv = ptr_t(new LLSocket(socket, new_pool)); if(port > 0) { apr_sockaddr_t* sa = NULL; @@ -133,7 +152,7 @@ LLSocket::ptr_t LLSocket::create(EType type, U16 port) APR_UNSPEC, port, 0, - rv->mPool()); + new_pool); if(ll_apr_warn_status(status)) { rv.reset(); @@ -141,8 +160,8 @@ LLSocket::ptr_t LLSocket::create(EType type, U16 port) } // This allows us to reuse the address on quick down/up. This // is unlikely to create problems. - ll_apr_warn_status(apr_socket_opt_set(rv->mSocket, APR_SO_REUSEADDR, 1)); - status = apr_socket_bind(rv->mSocket, sa); + ll_apr_warn_status(apr_socket_opt_set(socket, APR_SO_REUSEADDR, 1)); + status = apr_socket_bind(socket, sa); if(ll_apr_warn_status(status)) { rv.reset(); @@ -156,7 +175,7 @@ LLSocket::ptr_t LLSocket::create(EType type, U16 port) // to keep a queue of incoming connections for ACCEPT. lldebugs << "Setting listen state for socket." << llendl; status = apr_socket_listen( - rv->mSocket, + socket, LL_DEFAULT_LISTEN_BACKLOG); if(ll_apr_warn_status(status)) { @@ -177,28 +196,21 @@ LLSocket::ptr_t LLSocket::create(EType type, U16 port) } // static -LLSocket::ptr_t LLSocket::create(apr_status_t& status, LLSocket::ptr_t& listen_socket) +LLSocket::ptr_t LLSocket::create(apr_socket_t* socket, apr_pool_t* pool) { LLMemType m1(LLMemType::MTYPE_IO_TCP); - if (!listen_socket->getSocket()) - { - status = APR_ENOSOCKET; - return LLSocket::ptr_t(); - } - LLSocket::ptr_t rv(new LLSocket); - lldebugs << "accepting socket" << llendl; - status = apr_socket_accept(&rv->mSocket, listen_socket->getSocket(), rv->mPool()); - if (status != APR_SUCCESS) + LLSocket::ptr_t rv; + if(!socket) { - rv->mSocket = NULL; - rv.reset(); return rv; } + rv = ptr_t(new LLSocket(socket, pool)); rv->mPort = PORT_EPHEMERAL; rv->setNonBlocking(); return rv; } + bool LLSocket::blockingConnect(const LLHost& host) { if(!mSocket) return false; @@ -211,7 +223,7 @@ bool LLSocket::blockingConnect(const LLHost& host) APR_UNSPEC, host.getPort(), 0, - mPool()))) + mPool))) { return false; } @@ -222,11 +234,13 @@ bool LLSocket::blockingConnect(const LLHost& host) return true; } -LLSocket::LLSocket() : - mSocket(NULL), - mPool(LLThread::tldata().mRootPool), +LLSocket::LLSocket(apr_socket_t* socket, apr_pool_t* pool) : + mSocket(socket), + mPool(pool), mPort(PORT_INVALID) { + ll_debug_socket("Constructing wholely formed socket", mSocket); + LLMemType m1(LLMemType::MTYPE_IO_TCP); } LLSocket::~LLSocket() @@ -239,6 +253,10 @@ LLSocket::~LLSocket() apr_socket_close(mSocket); mSocket = NULL; } + if(mPool) + { + apr_pool_destroy(mPool); + } } // See http://dev.ariel-networks.com/apr/apr-tutorial/html/apr-tutorial-13.html#ss13.4 @@ -520,8 +538,10 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl( /// LLIOServerSocket::LLIOServerSocket( + apr_pool_t* pool, LLIOServerSocket::socket_t listener, factory_t factory) : + mPool(pool), mListenSocket(listener), mReactor(factory), mInitialized(false), @@ -583,15 +603,21 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl( lldebugs << "accepting socket" << llendl; PUMP_DEBUG; - apr_status_t status; - LLSocket::ptr_t llsocket(LLSocket::create(status, mListenSocket)); + apr_pool_t* new_pool = NULL; + apr_status_t status = apr_pool_create(&new_pool, mPool); + apr_socket_t* socket = NULL; + status = apr_socket_accept( + &socket, + mListenSocket->getSocket(), + new_pool); + LLSocket::ptr_t llsocket(LLSocket::create(socket, new_pool)); //EStatus rv = STATUS_ERROR; - if(llsocket && status == APR_SUCCESS) + if(llsocket) { PUMP_DEBUG; apr_sockaddr_t* remote_addr; - apr_socket_addr_get(&remote_addr, APR_REMOTE, llsocket->getSocket()); + apr_socket_addr_get(&remote_addr, APR_REMOTE, socket); char* remote_host_string; apr_sockaddr_ip_get(&remote_host_string, remote_addr); @@ -606,6 +632,7 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl( { chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(llsocket))); pump->addChain(chain, mResponseTimeout); + status = STATUS_OK; } else { @@ -614,8 +641,7 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl( } else { - char buf[256]; - llwarns << "Unable to accept linden socket: " << apr_strerror(status, buf, sizeof(buf)) << llendl; + llwarns << "Unable to create linden socket." << llendl; } PUMP_DEBUG; @@ -628,10 +654,11 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl( #if 0 LLIODataSocket::LLIODataSocket( U16 suggested_port, - U16 start_discovery_port) : + U16 start_discovery_port, + apr_pool_t* pool) : mSocket(NULL) { - if(PORT_INVALID == suggested_port) return; + if(!pool || (PORT_INVALID == suggested_port)) return; if(ll_apr_warn_status(apr_socket_create(&mSocket, APR_INET, SOCK_DGRAM, APR_PROTO_UDP, pool))) return; apr_sockaddr_t* sa = NULL; if(ll_apr_warn_status(apr_sockaddr_info_get(&sa, APR_ANYADDR, APR_UNSPEC, suggested_port, 0, pool))) return; diff --git a/indra/llmessage/lliosocket.h b/indra/llmessage/lliosocket.h index f0a6f25657..be0f7dfcc6 100644 --- a/indra/llmessage/lliosocket.h +++ b/indra/llmessage/lliosocket.h @@ -38,6 +38,7 @@ */ #include "lliopipe.h" +#include "apr_pools.h" #include "apr_network_io.h" #include "llchainio.h" @@ -87,22 +88,34 @@ public: * socket. If you intend the socket to be known to external * clients without prior port notification, do not use * PORT_EPHEMERAL. + * @param pool The apr pool to use. A child pool will be created + * and associated with the socket. * @param type The type of socket to create * @param port The port for the socket * @return A valid socket shared pointer if the call worked. */ static ptr_t create( + apr_pool_t* pool, EType type, U16 port = PORT_EPHEMERAL); /** - * @brief Create a LLSocket by accepting a connection from a listen socket. + * @brief Create a LLSocket when you already have an apr socket. * - * @param status Output. Status of the accept if a valid listen socket was passed. - * @param listen_socket The listen socket to use. + * This method assumes an ephemeral port. This is typically used + * by calls which spawn a socket such as a call to + * <code>accept()</code> as in the server socket. This call should + * not fail if you have a valid apr socket. + * Because of the nature of how accept() works, you are expected + * to create a new pool for the socket, use that pool for the + * accept, and pass it in here where it will be bound with the + * socket and destroyed at the same time. + * @param socket The apr socket to use + * @param pool The pool used to create the socket. *NOTE: The pool + * passed in will be DESTROYED. * @return A valid socket shared pointer if the call worked. */ - static ptr_t create(apr_status_t& status, ptr_t& listen_socket); + static ptr_t create(apr_socket_t* socket, apr_pool_t* pool); /** * @brief Perform a blocking connect to a host. Do not use in production. @@ -133,12 +146,6 @@ public: apr_socket_t* getSocket() const { return mSocket; } /** - * @brief Protected constructor since should only make sockets - * with one of the two <code>create()</code> calls. - */ - LLSocket(void); - - /** * @brief Set default socket options, with SO_NONBLOCK = 0 and a timeout in us. * @param timeout Number of microseconds to wait on this socket. Any * negative number means block-forever. TIMEOUT OF 0 IS NON-PORTABLE. @@ -167,8 +174,8 @@ protected: // The apr socket. apr_socket_t* mSocket; - // Our memory pool. - LLAPRPool mPool; + // our memory pool + apr_pool_t* mPool; // The port if we know it. U16 mPort; @@ -293,7 +300,7 @@ class LLIOServerSocket : public LLIOPipe public: typedef LLSocket::ptr_t socket_t; typedef boost::shared_ptr<LLChainIOFactory> factory_t; - LLIOServerSocket(socket_t listener, factory_t reactor); + LLIOServerSocket(apr_pool_t* pool, socket_t listener, factory_t reactor); virtual ~LLIOServerSocket(); /** @@ -325,6 +332,7 @@ protected: //@} protected: + apr_pool_t* mPool; socket_t mListenSocket; factory_t mReactor; bool mInitialized; @@ -358,7 +366,8 @@ public: */ LLIODataSocket( U16 suggested_port, - U16 start_discovery_port); + U16 start_discovery_port, + apr_pool_t* pool); virtual ~LLIODataSocket(); protected: diff --git a/indra/llmessage/llmail.cpp b/indra/llmessage/llmail.cpp index 8a898ab1b0..08b31e9c7a 100644 --- a/indra/llmessage/llmail.cpp +++ b/indra/llmessage/llmail.cpp @@ -50,7 +50,6 @@ #include "llstring.h" #include "lluuid.h" #include "net.h" -#include "llaprpool.h" // // constants @@ -58,7 +57,7 @@ const size_t LL_MAX_KNOWN_GOOD_MAIL_SIZE = 4096; static bool gMailEnabled = true; -static LLAPRPool gMailPool; +static apr_pool_t* gMailPool; static apr_sockaddr_t* gSockAddr; static apr_socket_t* gMailSocket; @@ -83,7 +82,7 @@ bool connect_smtp() gSockAddr->sa.sin.sin_family, SOCK_STREAM, APR_PROTO_TCP, - gMailPool()); + gMailPool); if(ll_apr_warn_status(status)) return false; status = apr_socket_connect(gMailSocket, gSockAddr); if(ll_apr_warn_status(status)) @@ -140,19 +139,19 @@ BOOL LLMail::send( } // static -void LLMail::init(const std::string& hostname) +void LLMail::init(const std::string& hostname, apr_pool_t* pool) { gMailSocket = NULL; - if (hostname.empty()) + if(hostname.empty() || !pool) { + gMailPool = NULL; gSockAddr = NULL; - gMailPool.destroy(); } else { - gMailPool.create(); + gMailPool = pool; - // Collect all the information into a sockaddr structure. the + // collect all the information into a socaddr sturcture. the // documentation is a bit unclear, but I either have to // specify APR_UNSPEC or not specify any flags. I am not sure // which option is better. @@ -162,7 +161,7 @@ void LLMail::init(const std::string& hostname) APR_UNSPEC, 25, APR_IPV4_ADDR_OK, - gMailPool()); + gMailPool); ll_apr_warn_status(status); } } diff --git a/indra/llmessage/llmail.h b/indra/llmessage/llmail.h index 0a5c532088..3791714363 100644 --- a/indra/llmessage/llmail.h +++ b/indra/llmessage/llmail.h @@ -27,13 +27,15 @@ #ifndef LL_LLMAIL_H #define LL_LLMAIL_H +typedef struct apr_pool_t apr_pool_t; + #include "llsd.h" class LLMail { public: // if hostname is NULL, then the host is resolved as 'mail' - static void init(const std::string& hostname); + static void init(const std::string& hostname, apr_pool_t* pool); // Allow all email transmission to be disabled/enabled. static void enable(bool mail_enabled); diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp index 4a7d326c0e..9988fcd9c0 100644 --- a/indra/llmessage/llproxy.cpp +++ b/indra/llmessage/llproxy.cpp @@ -49,7 +49,7 @@ static void tcp_close_channel(LLSocket::ptr_t* handle_ptr); // Close an open TCP LLProxy::LLProxy(): mHTTPProxyEnabled(false), - mProxyMutex(), + mProxyMutex(NULL), mUDPProxy(), mTCPProxy(), mHTTPProxy(), @@ -524,7 +524,7 @@ static apr_status_t tcp_blocking_handshake(LLSocket::ptr_t handle, char * dataou */ static LLSocket::ptr_t tcp_open_channel(LLHost host) { - LLSocket::ptr_t socket = LLSocket::create(LLSocket::STREAM_TCP); + LLSocket::ptr_t socket = LLSocket::create(NULL, LLSocket::STREAM_TCP); bool connected = socket->blockingConnect(host); if (!connected) { diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp index 89cfd66e1b..a8d2a0a224 100644 --- a/indra/llmessage/llpumpio.cpp +++ b/indra/llmessage/llpumpio.cpp @@ -37,7 +37,6 @@ #include "llmemtype.h" #include "llstl.h" #include "llstat.h" -#include "llthread.h" // These should not be enabled in production, but they can be // intensely useful during development for finding certain kinds of @@ -163,12 +162,14 @@ struct ll_delete_apr_pollset_fd_client_data /** * LLPumpIO */ -LLPumpIO::LLPumpIO(void) : +LLPumpIO::LLPumpIO(apr_pool_t* pool) : mState(LLPumpIO::NORMAL), mRebuildPollset(false), mPollset(NULL), mPollsetClientID(0), mNextLock(0), + mPool(NULL), + mCurrentPool(NULL), mCurrentPoolReallocCount(0), mChainsMutex(NULL), mCallbackMutex(NULL), @@ -177,24 +178,21 @@ LLPumpIO::LLPumpIO(void) : mCurrentChain = mRunningChains.end(); LLMemType m1(LLMemType::MTYPE_IO_PUMP); - initialize(); + initialize(pool); } LLPumpIO::~LLPumpIO() { LLMemType m1(LLMemType::MTYPE_IO_PUMP); -#if LL_THREADS_APR - if (mChainsMutex) apr_thread_mutex_destroy(mChainsMutex); - if (mCallbackMutex) apr_thread_mutex_destroy(mCallbackMutex); -#endif - mChainsMutex = NULL; - mCallbackMutex = NULL; - if(mPollset) - { -// lldebugs << "cleaning up pollset" << llendl; - apr_pollset_destroy(mPollset); - mPollset = NULL; - } + cleanup(); +} + +bool LLPumpIO::prime(apr_pool_t* pool) +{ + LLMemType m1(LLMemType::MTYPE_IO_PUMP); + cleanup(); + initialize(pool); + return ((pool == NULL) ? false : true); } bool LLPumpIO::addChain(const chain_t& chain, F32 timeout) @@ -354,7 +352,8 @@ bool LLPumpIO::setConditional(LLIOPipe* pipe, const apr_pollfd_t* poll) { // each fd needs a pool to work with, so if one was // not specified, use this pool. - value.second.p = (*mCurrentChain).mDescriptorsPool->operator()(); + // *FIX: Should it always be this pool? + value.second.p = mPool; } value.second.client_data = new S32(++mPollsetClientID); (*mCurrentChain).mDescriptors.push_back(value); @@ -826,15 +825,39 @@ void LLPumpIO::control(LLPumpIO::EControl op) } } -void LLPumpIO::initialize(void) +void LLPumpIO::initialize(apr_pool_t* pool) { LLMemType m1(LLMemType::MTYPE_IO_PUMP); - mPool.create(); + if(!pool) return; #if LL_THREADS_APR // SJB: Windows defaults to NESTED and OSX defaults to UNNESTED, so use UNNESTED explicitly. - apr_thread_mutex_create(&mChainsMutex, APR_THREAD_MUTEX_UNNESTED, mPool()); - apr_thread_mutex_create(&mCallbackMutex, APR_THREAD_MUTEX_UNNESTED, mPool()); + apr_thread_mutex_create(&mChainsMutex, APR_THREAD_MUTEX_UNNESTED, pool); + apr_thread_mutex_create(&mCallbackMutex, APR_THREAD_MUTEX_UNNESTED, pool); +#endif + mPool = pool; +} + +void LLPumpIO::cleanup() +{ + LLMemType m1(LLMemType::MTYPE_IO_PUMP); +#if LL_THREADS_APR + if(mChainsMutex) apr_thread_mutex_destroy(mChainsMutex); + if(mCallbackMutex) apr_thread_mutex_destroy(mCallbackMutex); #endif + mChainsMutex = NULL; + mCallbackMutex = NULL; + if(mPollset) + { +// lldebugs << "cleaning up pollset" << llendl; + apr_pollset_destroy(mPollset); + mPollset = NULL; + } + if(mCurrentPool) + { + apr_pool_destroy(mCurrentPool); + mCurrentPool = NULL; + } + mPool = NULL; } void LLPumpIO::rebuildPollset() @@ -862,19 +885,21 @@ void LLPumpIO::rebuildPollset() if(mCurrentPool && (0 == (++mCurrentPoolReallocCount % POLLSET_POOL_RECYCLE_COUNT))) { - mCurrentPool.destroy(); + apr_pool_destroy(mCurrentPool); + mCurrentPool = NULL; mCurrentPoolReallocCount = 0; } if(!mCurrentPool) { - mCurrentPool.create(mPool); + apr_status_t status = apr_pool_create(&mCurrentPool, mPool); + (void)ll_apr_warn_status(status); } // add all of the file descriptors run_it = mRunningChains.begin(); LLChainInfo::conditionals_t::iterator fd_it; LLChainInfo::conditionals_t::iterator fd_end; - apr_pollset_create(&mPollset, size, mCurrentPool(), 0); + apr_pollset_create(&mPollset, size, mCurrentPool, 0); for(; run_it != run_end; ++run_it) { fd_it = (*run_it).mDescriptors.begin(); @@ -1132,8 +1157,7 @@ bool LLPumpIO::handleChainError( LLPumpIO::LLChainInfo::LLChainInfo() : mInit(false), mLock(0), - mEOS(false), - mDescriptorsPool(new LLAPRPool(LLThread::tldata().mRootPool)) + mEOS(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 75c35ae7ab..9303c9d7fc 100644 --- a/indra/llmessage/llpumpio.h +++ b/indra/llmessage/llpumpio.h @@ -30,12 +30,11 @@ #define LL_LLPUMPIO_H #include <set> -#include <boost/shared_ptr.hpp> #if LL_LINUX // needed for PATH_MAX in APR. #include <sys/param.h> #endif -#include "llaprpool.h" +#include "apr_pools.h" #include "llbuffer.h" #include "llframetimer.h" #include "lliopipe.h" @@ -59,8 +58,9 @@ extern const F32 NEVER_CHAIN_EXPIRY_SECS; * <code>pump()</code> on a thread used for IO and call * <code>respond()</code> on a thread that is expected to do higher * level processing. You can call almost any other method from any - * thread - see notes for each method for details. - * + * thread - see notes for each method for details. In order for the + * threading abstraction to work, you need to call <code>prime()</code> + * with a valid apr pool. * A pump instance manages much of the state for the pipe, including * the list of pipes in the chain, the channel for each element in the * chain, the buffer, and if any pipe has marked the stream or process @@ -79,7 +79,7 @@ public: /** * @brief Constructor. */ - LLPumpIO(void); + LLPumpIO(apr_pool_t* pool); /** * @brief Destructor. @@ -87,6 +87,17 @@ public: ~LLPumpIO(); /** + * @brief Prepare this pump for usage. + * + * If you fail to call this method prior to use, the pump will + * try to work, but will not come with any thread locking + * mechanisms. + * @param pool The apr pool to use. + * @return Returns true if the pump is primed. + */ + bool prime(apr_pool_t* pool); + + /** * @brief Typedef for having a chain of pipes. */ typedef std::vector<LLIOPipe::ptr_t> chain_t; @@ -357,7 +368,6 @@ protected: typedef std::pair<LLIOPipe::ptr_t, apr_pollfd_t> pipe_conditional_t; typedef std::vector<pipe_conditional_t> conditionals_t; conditionals_t mDescriptors; - boost::shared_ptr<LLAPRPool> mDescriptorsPool; }; // All the running chains & info @@ -376,9 +386,9 @@ protected: callbacks_t mPendingCallbacks; callbacks_t mCallbacks; - // Memory pool for pollsets & mutexes. - LLAPRPool mPool; - LLAPRPool mCurrentPool; + // memory allocator for pollsets & mutexes. + apr_pool_t* mPool; + apr_pool_t* mCurrentPool; S32 mCurrentPoolReallocCount; #if LL_THREADS_APR @@ -390,7 +400,8 @@ protected: #endif protected: - void initialize(); + void initialize(apr_pool_t* pool); + void cleanup(); /** * @brief Given the internal state of the chains, rebuild the pollset diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index 91a5a8ce2c..fa03bb7512 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -41,7 +41,6 @@ #include "llstring.h" #include "apr_env.h" #include "llapr.h" -#include "llscopedvolatileaprpool.h" static const U32 HTTP_STATUS_PIPE_ERROR = 499; /** @@ -212,31 +211,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; - } } - LL_DEBUGS("Proxy") << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (!env_proxy.empty() ? env_proxy : "(null)") << LL_ENDL; - if (use_proxy && !env_proxy.empty()) + 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); } diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index 7d21e35f96..d0b0e178b8 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -97,10 +97,8 @@ std::string get_shared_secret(); class LLMessagePollInfo { public: - LLMessagePollInfo(void) : mPool(LLThread::tldata().mRootPool) { } apr_socket_t *mAPRSocketp; apr_pollfd_t mPollFD; - LLAPRPool mPool; }; namespace @@ -289,13 +287,20 @@ LLMessageSystem::LLMessageSystem(const std::string& filename, U32 port, } // LL_DEBUGS("Messaging") << << "*** port: " << mPort << llendl; - mPollInfop = new LLMessagePollInfo; - + // + // Create the data structure that we can poll on + // + if (!gAPRPoolp) + { + LL_ERRS("Messaging") << "No APR pool before message system initialization!" << llendl; + ll_init_apr(); + } apr_socket_t *aprSocketp = NULL; - apr_os_sock_put(&aprSocketp, (apr_os_sock_t*)&mSocket, mPollInfop->mPool()); + apr_os_sock_put(&aprSocketp, (apr_os_sock_t*)&mSocket, gAPRPoolp); + mPollInfop = new LLMessagePollInfo; mPollInfop->mAPRSocketp = aprSocketp; - mPollInfop->mPollFD.p = mPollInfop->mPool(); + mPollInfop->mPollFD.p = gAPRPoolp; mPollInfop->mPollFD.desc_type = APR_POLL_SOCKET; mPollInfop->mPollFD.reqevents = APR_POLLIN; mPollInfop->mPollFD.rtnevents = 0; diff --git a/indra/llmessage/tests/networkio.h b/indra/llmessage/tests/networkio.h index 23e1c791f4..2aff90ca1e 100644 --- a/indra/llmessage/tests/networkio.h +++ b/indra/llmessage/tests/networkio.h @@ -30,6 +30,7 @@ #define LL_NETWORKIO_H #include "llmemory.h" // LLSingleton +#include "llapr.h" #include "llares.h" #include "llpumpio.h" #include "llhttpclient.h" @@ -47,8 +48,14 @@ public: mServicePump(NULL), mDone(false) { + ll_init_apr(); + if (! gAPRPoolp) + { + throw std::runtime_error("Can't initialize APR"); + } + // Create IO Pump to use for HTTP Requests. - mServicePump = new LLPumpIO; + mServicePump = new LLPumpIO(gAPRPoolp); LLHTTPClient::setPump(*mServicePump); if (ll_init_ares() == NULL || !gAres->isInitialized()) { diff --git a/indra/llplugin/llplugininstance.cpp b/indra/llplugin/llplugininstance.cpp index e8efb233ff..7cde82a20e 100644 --- a/indra/llplugin/llplugininstance.cpp +++ b/indra/llplugin/llplugininstance.cpp @@ -29,7 +29,8 @@ #include "linden_common.h" #include "llplugininstance.h" -#include "llthread.h" // Needed for LLThread::tldata().mRootPool + +#include "llapr.h" #if LL_WINDOWS #include "direct.h" // needed for _chdir() @@ -51,7 +52,6 @@ const char *LLPluginInstance::PLUGIN_INIT_FUNCTION_NAME = "LLPluginInitEntryPoin * @param[in] owner Plugin instance. TODO:DOC is this a good description of what "owner" is? */ LLPluginInstance::LLPluginInstance(LLPluginInstanceMessageListener *owner) : - mDSOHandlePool(LLThread::tldata().mRootPool), mDSOHandle(NULL), mPluginUserData(NULL), mPluginSendMessageFunction(NULL) @@ -97,7 +97,7 @@ int LLPluginInstance::load(const std::string& plugin_dir, std::string &plugin_fi int result = apr_dso_load(&mDSOHandle, plugin_file.c_str(), - mDSOHandlePool()); + gAPRPoolp); if(result != APR_SUCCESS) { char buf[1024]; diff --git a/indra/llplugin/llplugininstance.h b/indra/llplugin/llplugininstance.h index ee28f68e83..3643a15d8c 100644 --- a/indra/llplugin/llplugininstance.h +++ b/indra/llplugin/llplugininstance.h @@ -30,7 +30,6 @@ #include "llstring.h" #include "llapr.h" -#include "llaprpool.h" #include "apr_dso.h" @@ -89,7 +88,6 @@ private: static void staticReceiveMessage(const char *message_string, void **user_data); void receiveMessage(const char *message_string); - LLAPRPool mDSOHandlePool; apr_dso_handle_t *mDSOHandle; void *mPluginUserData; diff --git a/indra/llplugin/llpluginmessagepipe.cpp b/indra/llplugin/llpluginmessagepipe.cpp index dd47300b9c..8d13e38ad5 100644 --- a/indra/llplugin/llpluginmessagepipe.cpp +++ b/indra/llplugin/llpluginmessagepipe.cpp @@ -92,6 +92,8 @@ void LLPluginMessagePipeOwner::killMessagePipe(void) } LLPluginMessagePipe::LLPluginMessagePipe(LLPluginMessagePipeOwner *owner, LLSocket::ptr_t socket): + mInputMutex(gAPRPoolp), + mOutputMutex(gAPRPoolp), mOwner(owner), mSocket(socket) { diff --git a/indra/llplugin/llpluginprocesschild.cpp b/indra/llplugin/llpluginprocesschild.cpp index fd63fdde81..f8a282184e 100644 --- a/indra/llplugin/llpluginprocesschild.cpp +++ b/indra/llplugin/llpluginprocesschild.cpp @@ -40,7 +40,7 @@ LLPluginProcessChild::LLPluginProcessChild() { mState = STATE_UNINITIALIZED; mInstance = NULL; - mSocket = LLSocket::create(LLSocket::STREAM_TCP); + mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); mSleepTime = PLUGIN_IDLE_SECONDS; // default: send idle messages at 100Hz mCPUElapsed = 0.0f; mBlockingRequest = false; diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp index 7aec72731e..110fac0f23 100644 --- a/indra/llplugin/llpluginprocessparent.cpp +++ b/indra/llplugin/llpluginprocessparent.cpp @@ -33,7 +33,6 @@ #include "llpluginmessageclasses.h" #include "llapr.h" -#include "llscopedvolatileaprpool.h" //virtual LLPluginProcessParentOwner::~LLPluginProcessParentOwner() @@ -43,7 +42,6 @@ LLPluginProcessParentOwner::~LLPluginProcessParentOwner() bool LLPluginProcessParent::sUseReadThread = false; apr_pollset_t *LLPluginProcessParent::sPollSet = NULL; -LLAPRPool LLPluginProcessParent::sPollSetPool; bool LLPluginProcessParent::sPollsetNeedsRebuild = false; LLMutex *LLPluginProcessParent::sInstancesMutex; std::list<LLPluginProcessParent*> LLPluginProcessParent::sInstances; @@ -54,7 +52,7 @@ class LLPluginProcessParentPollThread: public LLThread { public: LLPluginProcessParentPollThread() : - LLThread("LLPluginProcessParentPollThread") + LLThread("LLPluginProcessParentPollThread", gAPRPoolp) { } protected: @@ -79,11 +77,12 @@ protected: }; -LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner* owner) +LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner): + mIncomingQueueMutex(gAPRPoolp) { if(!sInstancesMutex) { - sInstancesMutex = new LLMutex; + sInstancesMutex = new LLMutex(gAPRPoolp); } mOwner = owner; @@ -96,7 +95,6 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner* owner) mBlocked = false; mPolledInput = false; mPollFD.client_data = NULL; - mPollFDPool.create(); mPluginLaunchTimeout = 60.0f; mPluginLockupTimeout = 15.0f; @@ -173,28 +171,44 @@ void LLPluginProcessParent::init(const std::string &launcher_filename, const std bool LLPluginProcessParent::accept() { bool result = false; + apr_status_t status = APR_EGENERAL; + apr_socket_t *new_socket = NULL; + + status = apr_socket_accept( + &new_socket, + mListenSocket->getSocket(), + gAPRPoolp); - mSocket = LLSocket::create(status, mListenSocket); if(status == APR_SUCCESS) { // llinfos << "SUCCESS" << llendl; // Success. Create a message pipe on the new socket + + // we MUST create a new pool for the LLSocket, since it will take ownership of it and delete it in its destructor! + apr_pool_t* new_pool = NULL; + status = apr_pool_create(&new_pool, gAPRPoolp); + + mSocket = LLSocket::create(new_socket, new_pool); new LLPluginMessagePipe(this, mSocket); result = true; } + else if(APR_STATUS_IS_EAGAIN(status)) + { +// llinfos << "EAGAIN" << llendl; + + // No incoming connections. This is not an error. + status = APR_SUCCESS; + } else { - mSocket.reset(); - // EAGAIN means "No incoming connections". This is not an error. - if (!APR_STATUS_IS_EAGAIN(status)) - { - // Some other error. - ll_apr_warn_status(status); - errorState(); - } +// llinfos << "Error:" << llendl; + ll_apr_warn_status(status); + + // Some other error. + errorState(); } return result; @@ -260,10 +274,10 @@ void LLPluginProcessParent::idle(void) case STATE_INITIALIZED: { + apr_status_t status = APR_SUCCESS; - LLScopedVolatileAPRPool addr_pool; apr_sockaddr_t* addr = NULL; - mListenSocket = LLSocket::create(LLSocket::STREAM_TCP); + mListenSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); mBoundPort = 0; // This code is based on parts of LLSocket::create() in lliosocket.cpp. @@ -274,7 +288,7 @@ void LLPluginProcessParent::idle(void) APR_INET, 0, // port 0 = ephemeral ("find me a port") 0, - addr_pool); + gAPRPoolp); if(ll_apr_warn_status(status)) { @@ -587,7 +601,7 @@ void LLPluginProcessParent::setMessagePipe(LLPluginMessagePipe *message_pipe) if(message_pipe != NULL) { // Set up the apr_pollfd_t - mPollFD.p = mPollFDPool(); + mPollFD.p = gAPRPoolp; mPollFD.desc_type = APR_POLL_SOCKET; mPollFD.reqevents = APR_POLLIN|APR_POLLERR|APR_POLLHUP; mPollFD.rtnevents = 0; @@ -634,7 +648,6 @@ void LLPluginProcessParent::updatePollset() // delete the existing pollset. apr_pollset_destroy(sPollSet); sPollSet = NULL; - sPollSetPool.destroy(); } std::list<LLPluginProcessParent*>::iterator iter; @@ -657,14 +670,12 @@ void LLPluginProcessParent::updatePollset() { #ifdef APR_POLLSET_NOCOPY // The pollset doesn't exist yet. Create it now. - sPollSetPool.create(); - apr_status_t status = apr_pollset_create(&sPollSet, count, sPollSetPool(), APR_POLLSET_NOCOPY); + apr_status_t status = apr_pollset_create(&sPollSet, count, gAPRPoolp, APR_POLLSET_NOCOPY); if(status != APR_SUCCESS) { #endif // APR_POLLSET_NOCOPY LL_WARNS("PluginPoll") << "Couldn't create pollset. Falling back to non-pollset mode." << LL_ENDL; sPollSet = NULL; - sPollSetPool.destroy(); #ifdef APR_POLLSET_NOCOPY } else diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h index 74b7e9f50c..26c6b0c402 100644 --- a/indra/llplugin/llpluginprocessparent.h +++ b/indra/llplugin/llpluginprocessparent.h @@ -178,9 +178,7 @@ private: static bool sUseReadThread; apr_pollfd_t mPollFD; - LLAPRPool mPollFDPool; static apr_pollset_t *sPollSet; - static LLAPRPool sPollSetPool; static bool sPollsetNeedsRebuild; static LLMutex *sInstancesMutex; static std::list<LLPluginProcessParent*> sInstances; diff --git a/indra/llplugin/llpluginsharedmemory.cpp b/indra/llplugin/llpluginsharedmemory.cpp index e2ff645a9c..63ff5085c6 100644 --- a/indra/llplugin/llpluginsharedmemory.cpp +++ b/indra/llplugin/llpluginsharedmemory.cpp @@ -187,8 +187,7 @@ bool LLPluginSharedMemory::create(size_t size) mName += createName(); mSize = size; - mPool.create(); - apr_status_t status = apr_shm_create( &(mImpl->mAprSharedMemory), mSize, mName.c_str(), mPool()); + apr_status_t status = apr_shm_create( &(mImpl->mAprSharedMemory), mSize, mName.c_str(), gAPRPoolp ); if(ll_apr_warn_status(status)) { @@ -211,7 +210,7 @@ bool LLPluginSharedMemory::destroy(void) } mImpl->mAprSharedMemory = NULL; } - mPool.destroy(); + return true; } @@ -220,8 +219,7 @@ bool LLPluginSharedMemory::attach(const std::string &name, size_t size) mName = name; mSize = size; - mPool.create(); - apr_status_t status = apr_shm_attach( &(mImpl->mAprSharedMemory), mName.c_str(), mPool() ); + apr_status_t status = apr_shm_attach( &(mImpl->mAprSharedMemory), mName.c_str(), gAPRPoolp ); if(ll_apr_warn_status(status)) { @@ -243,7 +241,6 @@ bool LLPluginSharedMemory::detach(void) } mImpl->mAprSharedMemory = NULL; } - mPool.destroy(); return true; } diff --git a/indra/llplugin/llpluginsharedmemory.h b/indra/llplugin/llpluginsharedmemory.h index 84b7a58c32..c6cd49cabb 100644 --- a/indra/llplugin/llpluginsharedmemory.h +++ b/indra/llplugin/llpluginsharedmemory.h @@ -28,8 +28,6 @@ #ifndef LL_LLPLUGINSHAREDMEMORY_H #define LL_LLPLUGINSHAREDMEMORY_H -#include "llaprpool.h" - class LLPluginSharedMemoryPlatformImpl; /** @@ -110,7 +108,6 @@ private: bool close(void); bool unlink(void); - LLAPRPool mPool; std::string mName; size_t mSize; void *mMappedAddress; diff --git a/indra/llplugin/slplugin/slplugin.cpp b/indra/llplugin/slplugin/slplugin.cpp index ff86e4e135..516a58db88 100644 --- a/indra/llplugin/slplugin/slplugin.cpp +++ b/indra/llplugin/slplugin/slplugin.cpp @@ -176,6 +176,8 @@ int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdL int main(int argc, char **argv) #endif { + ll_init_apr(); + // Set up llerror logging { LLError::initForApplication("."); @@ -391,6 +393,8 @@ int main(int argc, char **argv) delete plugin; + ll_cleanup_apr(); + return 0; } diff --git a/indra/llvfs/lllfsthread.cpp b/indra/llvfs/lllfsthread.cpp index bf49b9668e..3d3ed9f6d4 100644 --- a/indra/llvfs/lllfsthread.cpp +++ b/indra/llvfs/lllfsthread.cpp @@ -67,6 +67,10 @@ LLLFSThread::LLLFSThread(bool threaded) : LLQueuedThread("LFS", threaded), mPriorityCounter(PRIORITY_LOWBITS) { + if(!mLocalAPRFilePoolp) + { + mLocalAPRFilePoolp = new LLVolatileAPRPool() ; + } } LLLFSThread::~LLLFSThread() @@ -178,7 +182,8 @@ bool LLLFSThread::Request::processRequest() if (mOperation == FILE_READ) { llassert(mOffset >= 0); - LLAPRFile infile(mFileName, LL_APR_RB); + LLAPRFile infile ; // auto-closes + infile.open(mFileName, LL_APR_RB, mThread->getLocalAPRFilePool()); if (!infile.getFileHandle()) { llwarns << "LLLFS: Unable to read file: " << mFileName << llendl; @@ -200,7 +205,8 @@ bool LLLFSThread::Request::processRequest() apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY; if (mOffset < 0) flags |= APR_APPEND; - LLAPRFile outfile(mFileName, flags); + LLAPRFile outfile ; // auto-closes + outfile.open(mFileName, flags, mThread->getLocalAPRFilePool()); if (!outfile.getFileHandle()) { llwarns << "LLLFS: Unable to write file: " << mFileName << llendl; diff --git a/indra/llvfs/llvfs.cpp b/indra/llvfs/llvfs.cpp index ade19f8103..82c926620a 100644 --- a/indra/llvfs/llvfs.cpp +++ b/indra/llvfs/llvfs.cpp @@ -234,7 +234,7 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename mDataFP(NULL), mIndexFP(NULL) { - mDataMutex = new LLMutex; + mDataMutex = new LLMutex(0); S32 i; for (i = 0; i < VFSLOCK_COUNT; i++) @@ -2098,7 +2098,8 @@ void LLVFS::dumpFiles() std::string filename = id.asString() + extension; llinfos << " Writing " << filename << llendl; - LLAPRFile outfile(filename, LL_APR_WB); + LLAPRFile outfile; + outfile.open(filename, LL_APR_WB); outfile.write(&buffer[0], size); outfile.close(); diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h index 77d6d19663..6bc272c009 100644 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h +++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h @@ -37,6 +37,7 @@ extern "C" { #include <stdio.h> #include <gst/gst.h> +#include "apr_pools.h" #include "apr_dso.h" } diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp index 93a10424dd..2e4baaa9eb 100644 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp +++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp @@ -28,18 +28,16 @@ #if LL_GSTREAMER010_ENABLED -#include "linden_common.h" - #include <string> extern "C" { #include <gst/gst.h> +#include "apr_pools.h" #include "apr_dso.h" } #include "llmediaimplgstreamertriviallogging.h" -#include "llaprpool.h" #define LL_GST_SYM(REQ, GSTSYM, RTN, ...) RTN (*ll##GSTSYM)(__VA_ARGS__) = NULL #include "llmediaimplgstreamer_syms_raw.inc" @@ -58,7 +56,7 @@ void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname) } static bool sSymsGrabbed = false; -static LLAPRPool sSymGSTDSOMemoryPool; +static apr_pool_t *sSymGSTDSOMemoryPool = NULL; static apr_dso_handle_t *sSymGSTDSOHandleG = NULL; static apr_dso_handle_t *sSymGSTDSOHandleV = NULL; @@ -80,11 +78,11 @@ bool grab_gst_syms(std::string gst_dso_name, #define LL_GST_SYM(REQ, GSTSYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##GSTSYM, sSymGSTDSOHandle, #GSTSYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #GSTSYM); if (REQ) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #GSTSYM, (void*)ll##GSTSYM);}while(0) //attempt to load the shared libraries - sSymGSTDSOMemoryPool.create(); + apr_pool_create(&sSymGSTDSOMemoryPool, NULL); if ( APR_SUCCESS == (rv = apr_dso_load(&sSymGSTDSOHandle, gst_dso_name.c_str(), - sSymGSTDSOMemoryPool()) )) + sSymGSTDSOMemoryPool) )) { INFOMSG("Found DSO: %s", gst_dso_name.c_str()); #include "llmediaimplgstreamer_syms_raw.inc" @@ -98,7 +96,7 @@ bool grab_gst_syms(std::string gst_dso_name, if ( APR_SUCCESS == (rv = apr_dso_load(&sSymGSTDSOHandle, gst_dso_name_vid.c_str(), - sSymGSTDSOMemoryPool()) )) + sSymGSTDSOMemoryPool) )) { INFOMSG("Found DSO: %s", gst_dso_name_vid.c_str()); #include "llmediaimplgstreamer_syms_rawv.inc" @@ -152,7 +150,8 @@ void ungrab_gst_syms() if ( sSymGSTDSOMemoryPool ) { - sSymGSTDSOMemoryPool.destroy(); + apr_pool_destroy(sSymGSTDSOMemoryPool); + sSymGSTDSOMemoryPool = NULL; } // NULL-out all of the symbols we'd grabbed diff --git a/indra/media_plugins/webkit/linux_volume_catcher.cpp b/indra/media_plugins/webkit/linux_volume_catcher.cpp index 94dfd80700..91be3a89e9 100644 --- a/indra/media_plugins/webkit/linux_volume_catcher.cpp +++ b/indra/media_plugins/webkit/linux_volume_catcher.cpp @@ -65,7 +65,7 @@ extern "C" { #undef LL_PA_SYM static bool sSymsGrabbed = false; -static LLAPRPool sSymPADSOMemoryPool; +static apr_pool_t *sSymPADSOMemoryPool = NULL; static apr_dso_handle_t *sSymPADSOHandleG = NULL; bool grab_pa_syms(std::string pulse_dso_name) @@ -84,11 +84,11 @@ bool grab_pa_syms(std::string pulse_dso_name) #define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##PASYM, sSymPADSOHandle, #PASYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #PASYM); if (REQUIRED) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #PASYM, (void*)ll##PASYM);}while(0) //attempt to load the shared library - sSymPADSOMemoryPool.create(); + apr_pool_create(&sSymPADSOMemoryPool, NULL); if ( APR_SUCCESS == (rv = apr_dso_load(&sSymPADSOHandle, pulse_dso_name.c_str(), - sSymPADSOMemoryPool()) )) + sSymPADSOMemoryPool) )) { INFOMSG("Found DSO: %s", pulse_dso_name.c_str()); @@ -130,8 +130,12 @@ void ungrab_pa_syms() apr_dso_unload(sSymPADSOHandleG); sSymPADSOHandleG = NULL; } - - sSymPADSOMemoryPool.destroy(); + + if ( sSymPADSOMemoryPool ) + { + apr_pool_destroy(sSymPADSOMemoryPool); + sSymPADSOMemoryPool = NULL; + } // NULL-out all of the symbols we'd grabbed #define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{ll##PASYM = NULL;}while(0) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index be4ec93946..15f1bbd1b1 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -5657,6 +5657,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>MemoryPrivatePoolSize</key> + <map> + <key>Comment</key> + <string>Size of the private memory pool in MB (min. value is 256)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>512</integer> + </map> <key>MemProfiling</key> <map> <key>Comment</key> diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index b9125ec8d3..729eb92e94 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1168,15 +1168,12 @@ private: std::vector<LLWearable*> mWearablesAwaitingItems; }; -void LLAgentWearables::createStandardWearables(BOOL female) +void LLAgentWearables::createStandardWearables() { - llwarns << "Creating Standard " << (female ? "female" : "male") - << " Wearables" << llendl; + llwarns << "Creating standard wearables" << llendl; if (!isAgentAvatarValid()) return; - gAgentAvatarp->setSex(female ? SEX_FEMALE : SEX_MALE); - const BOOL create[LLWearableType::WT_COUNT] = { TRUE, //LLWearableType::WT_SHAPE diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 252b812c27..01cae3ffd8 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -56,7 +56,7 @@ public: LLAgentWearables(); virtual ~LLAgentWearables(); void setAvatarObject(LLVOAvatarSelf *avatar); - void createStandardWearables(BOOL female); + void createStandardWearables(); void cleanup(); void dump(); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 3cb9b77010..0666d22f10 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2264,6 +2264,85 @@ void LLAppearanceMgr::updateIsDirty() } } +// *HACK: Must match name in Library or agent inventory +const std::string ROOT_GESTURES_FOLDER = "Gestures"; +const std::string COMMON_GESTURES_FOLDER = "Common Gestures"; +const std::string MALE_GESTURES_FOLDER = "Male Gestures"; +const std::string FEMALE_GESTURES_FOLDER = "Female Gestures"; +const std::string SPEECH_GESTURES_FOLDER = "Speech Gestures"; +const std::string OTHER_GESTURES_FOLDER = "Other Gestures"; + +void LLAppearanceMgr::copyLibraryGestures() +{ + llinfos << "Copying library gestures" << llendl; + + // Copy gestures + LLUUID lib_gesture_cat_id = + gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE,false,true); + if (lib_gesture_cat_id.isNull()) + { + llwarns << "Unable to copy gestures, source category not found" << llendl; + } + LLUUID dst_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE); + + std::vector<std::string> gesture_folders_to_copy; + gesture_folders_to_copy.push_back(MALE_GESTURES_FOLDER); + gesture_folders_to_copy.push_back(FEMALE_GESTURES_FOLDER); + gesture_folders_to_copy.push_back(COMMON_GESTURES_FOLDER); + gesture_folders_to_copy.push_back(SPEECH_GESTURES_FOLDER); + gesture_folders_to_copy.push_back(OTHER_GESTURES_FOLDER); + + for(std::vector<std::string>::iterator it = gesture_folders_to_copy.begin(); + it != gesture_folders_to_copy.end(); + ++it) + { + std::string& folder_name = *it; + + LLPointer<LLInventoryCallback> cb(NULL); + + // After copying gestures, activate Common, Other, plus + // Male and/or Female, depending upon the initial outfit gender. + ESex gender = gAgentAvatarp->getSex(); + + std::string activate_male_gestures; + std::string activate_female_gestures; + switch (gender) { + case SEX_MALE: + activate_male_gestures = MALE_GESTURES_FOLDER; + break; + case SEX_FEMALE: + activate_female_gestures = FEMALE_GESTURES_FOLDER; + break; + case SEX_BOTH: + activate_male_gestures = MALE_GESTURES_FOLDER; + activate_female_gestures = FEMALE_GESTURES_FOLDER; + break; + } + + if (folder_name == activate_male_gestures || + folder_name == activate_female_gestures || + folder_name == COMMON_GESTURES_FOLDER || + folder_name == OTHER_GESTURES_FOLDER) + { + cb = new ActivateGestureCallback; + } + + LLUUID cat_id = findDescendentCategoryIDByName(lib_gesture_cat_id,folder_name); + if (cat_id.isNull()) + { + llwarns << "failed to find gesture folder for " << folder_name << llendl; + } + else + { + llinfos << "initiating fetch and copy for " << folder_name << " cat_id " << cat_id << llendl; + callAfterCategoryFetch(cat_id, + boost::bind(&LLAppearanceMgr::shallowCopyCategory, + &LLAppearanceMgr::instance(), + cat_id, dst_id, cb)); + } + } +} + void LLAppearanceMgr::autopopulateOutfits() { // If this is the very first time the user has logged into viewer2+ (from a legacy viewer, or new account) @@ -2285,9 +2364,16 @@ void LLAppearanceMgr::autopopulateOutfits() void LLAppearanceMgr::onFirstFullyVisible() { gAgentAvatarp->debugAvatarVisible(); + // The auto-populate is failing at the point of generating outfits // folders, so don't do the library copy until that is resolved. // autopopulateOutfits(); + + // If this is the first time we've ever logged in, + // then copy default gestures from the library. + if (gAgent.isFirstLogin()) { + copyLibraryGestures(); + } } bool LLAppearanceMgr::updateBaseOutfit() diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 4b1d95cf25..c1d561781d 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -151,6 +151,9 @@ public: // Create initial outfits from library. void autopopulateOutfits(); + + // Copy initial gestures from library. + void copyLibraryGestures(); void wearBaseOutfit(); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 11e2e1e607..0e57abd472 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -724,7 +724,7 @@ bool LLAppViewer::init() //set the max heap size. initMaxHeapSize() ; - LLPrivateMemoryPoolManager::initClass((BOOL)gSavedSettings.getBOOL("MemoryPrivatePoolEnabled")) ; + LLPrivateMemoryPoolManager::initClass((BOOL)gSavedSettings.getBOOL("MemoryPrivatePoolEnabled"), (U32)gSavedSettings.getU32("MemoryPrivatePoolSize")) ; // write Google Breakpad minidump files to our log directory std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); @@ -1124,63 +1124,25 @@ void LLAppViewer::checkMemory() { const static F32 MEMORY_CHECK_INTERVAL = 1.0f ; //second //const static F32 MAX_QUIT_WAIT_TIME = 30.0f ; //seconds - const static U32 MAX_SIZE_CHECKED_MEMORY_BLOCK = 64 * 1024 * 1024 ; //64 MB - //static F32 force_quit_timer = MAX_QUIT_WAIT_TIME + MEMORY_CHECK_INTERVAL ; - static void* last_reserved_address = NULL ; + //static F32 force_quit_timer = MAX_QUIT_WAIT_TIME + MEMORY_CHECK_INTERVAL ; - if(MEMORY_CHECK_INTERVAL > mMemCheckTimer.getElapsedTimeF32()) + if(!gGLManager.mDebugGPU) { return ; } - mMemCheckTimer.reset() ; - - if(gGLManager.mDebugGPU) - { - //update the availability of memory - LLMemory::updateMemoryInfo() ; - } - //check the virtual address space fragmentation - if(!last_reserved_address) - { - last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ; - } - else + if(MEMORY_CHECK_INTERVAL > mMemCheckTimer.getElapsedTimeF32()) { - last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ; - if(!last_reserved_address) //failed, try once more - { - last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ; - } + return ; } + mMemCheckTimer.reset() ; - S32 is_low = !last_reserved_address || LLMemory::isMemoryPoolLow() ; - - //if(is_low < 0) //to force quit - //{ - // if(force_quit_timer > MAX_QUIT_WAIT_TIME) //just hit the limit for the first time - // { - // //send out the notification to tell the viewer is about to quit in 30 seconds. - // LLNotification::Params params("ForceQuitDueToLowMemory"); - // LLNotifications::instance().add(params); + //update the availability of memory + LLMemory::updateMemoryInfo() ; - // force_quit_timer = MAX_QUIT_WAIT_TIME - MEMORY_CHECK_INTERVAL ; - // } - // else - // { - // force_quit_timer -= MEMORY_CHECK_INTERVAL ; - // if(force_quit_timer < 0.f) - // { - // forceQuit() ; //quit - // } - // } - //} - //else - //{ - // force_quit_timer = MAX_QUIT_WAIT_TIME + MEMORY_CHECK_INTERVAL ; - //} + bool is_low = LLMemory::isMemoryPoolLow() ; - LLPipeline::throttleNewMemoryAllocation(!is_low ? FALSE : TRUE) ; + LLPipeline::throttleNewMemoryAllocation(is_low) ; if(is_low) { @@ -1213,7 +1175,7 @@ bool LLAppViewer::mainLoop() //------------------------------------------- // Create IO Pump to use for HTTP Requests. - gServicePump = new LLPumpIO; + gServicePump = new LLPumpIO(gAPRPoolp); LLHTTPClient::setPump(*gServicePump); LLCurl::setCAFile(gDirUtilp->getCAFile()); @@ -1572,16 +1534,16 @@ bool LLAppViewer::cleanup() } // *TODO - generalize this and move DSO wrangling to a helper class -brad - for(std::map<apr_dso_handle_t*, boost::shared_ptr<LLAPRPool> >::iterator plugin = mPlugins.begin(); - plugin != mPlugins.end(); ++plugin) + std::set<struct apr_dso_handle_t *>::const_iterator i; + for(i = mPlugins.begin(); i != mPlugins.end(); ++i) { int (*ll_plugin_stop_func)(void) = NULL; - apr_status_t rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_stop_func, plugin->first, "ll_plugin_stop"); + apr_status_t rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_stop_func, *i, "ll_plugin_stop"); ll_plugin_stop_func(); - rv = apr_dso_unload(plugin->first); + rv = apr_dso_unload(*i); } - mPlugins.clear(); // Forget handles and destroy all memory pools. + mPlugins.clear(); //flag all elements as needing to be destroyed immediately // to ensure shutdown order @@ -2019,7 +1981,7 @@ bool LLAppViewer::initThreads() if (LLFastTimer::sLog || LLFastTimer::sMetricLog) { - LLFastTimer::sLogLock = new LLMutex; + LLFastTimer::sLogLock = new LLMutex(NULL); mFastTimerLogThread = new LLFastTimerLogThread(LLFastTimer::sLogName); mFastTimerLogThread->start(); } @@ -3267,7 +3229,8 @@ void LLAppViewer::handleViewerCrash() else crash_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,ERROR_MARKER_FILE_NAME); llinfos << "Creating crash marker file " << crash_file_name << llendl; - LLAPRFile crash_file(crash_file_name, LL_APR_W); + LLAPRFile crash_file ; + crash_file.open(crash_file_name, LL_APR_W); if (crash_file.getFileHandle()) { LL_INFOS("MarkerFile") << "Created crash marker file " << crash_file_name << LL_ENDL; @@ -3331,10 +3294,11 @@ bool LLAppViewer::anotherInstanceRunning() LL_DEBUGS("MarkerFile") << "Checking marker file for lock..." << LL_ENDL; //Freeze case checks - if (LLAPRFile::isExist(marker_file, LL_APR_RB)) + if (LLAPRFile::isExist(marker_file, NULL, LL_APR_RB)) { // File exists, try opening with write permissions - LLAPRFile outfile(marker_file, LL_APR_WB); + LLAPRFile outfile ; + outfile.open(marker_file, LL_APR_WB); apr_file_t* fMarker = outfile.getFileHandle() ; if (!fMarker) { @@ -3373,25 +3337,25 @@ void LLAppViewer::initMarkerFile() std::string llerror_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LLERROR_MARKER_FILE_NAME); std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME); - if (LLAPRFile::isExist(mMarkerFileName, LL_APR_RB) && !anotherInstanceRunning()) + if (LLAPRFile::isExist(mMarkerFileName, NULL, LL_APR_RB) && !anotherInstanceRunning()) { gLastExecEvent = LAST_EXEC_FROZE; LL_INFOS("MarkerFile") << "Exec marker found: program froze on previous execution" << LL_ENDL; } - if(LLAPRFile::isExist(logout_marker_file, LL_APR_RB)) + if(LLAPRFile::isExist(logout_marker_file, NULL, LL_APR_RB)) { gLastExecEvent = LAST_EXEC_LOGOUT_FROZE; LL_INFOS("MarkerFile") << "Last exec LLError crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL; LLAPRFile::remove(logout_marker_file); } - if(LLAPRFile::isExist(llerror_marker_file, LL_APR_RB)) + if(LLAPRFile::isExist(llerror_marker_file, NULL, LL_APR_RB)) { if(gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) gLastExecEvent = LAST_EXEC_LOGOUT_CRASH; else gLastExecEvent = LAST_EXEC_LLERROR_CRASH; LL_INFOS("MarkerFile") << "Last exec LLError crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL; LLAPRFile::remove(llerror_marker_file); } - if(LLAPRFile::isExist(error_marker_file, LL_APR_RB)) + if(LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB)) { if(gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) gLastExecEvent = LAST_EXEC_LOGOUT_CRASH; else gLastExecEvent = LAST_EXEC_OTHER_CRASH; @@ -3407,7 +3371,7 @@ void LLAppViewer::initMarkerFile() // Create the marker file for this execution & lock it apr_status_t s; - s = mMarkerFile.open(mMarkerFileName, LL_APR_W, LLAPRFile::long_lived); + s = mMarkerFile.open(mMarkerFileName, LL_APR_W, TRUE); if (s == APR_SUCCESS && mMarkerFile.getFileHandle()) { @@ -4653,7 +4617,8 @@ void LLAppViewer::sendLogoutRequest() gLogoutInProgress = TRUE; mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LOGOUT_MARKER_FILE_NAME); - LLAPRFile outfile(mLogoutMarkerFileName, LL_APR_W); + LLAPRFile outfile ; + outfile.open(mLogoutMarkerFileName, LL_APR_W); mLogoutMarkerFile = outfile.getFileHandle() ; if (mLogoutMarkerFile) { @@ -5105,15 +5070,14 @@ void LLAppViewer::loadEventHostModule(S32 listen_port) } #endif // LL_WINDOWS - boost::shared_ptr<LLAPRPool> eventhost_dso_memory_pool_ptr(new LLAPRPool); - LLAPRPool& eventhost_dso_memory_pool(*eventhost_dso_memory_pool_ptr); - apr_dso_handle_t* eventhost_dso_handle = NULL; + apr_dso_handle_t * eventhost_dso_handle = NULL; + apr_pool_t * eventhost_dso_memory_pool = NULL; //attempt to load the shared library - eventhost_dso_memory_pool.create(); + apr_pool_create(&eventhost_dso_memory_pool, NULL); apr_status_t rv = apr_dso_load(&eventhost_dso_handle, dso_path.c_str(), - eventhost_dso_memory_pool()); + eventhost_dso_memory_pool); llassert_always(! ll_apr_warn_status(rv, eventhost_dso_handle)); llassert_always(eventhost_dso_handle != NULL); @@ -5133,8 +5097,7 @@ void LLAppViewer::loadEventHostModule(S32 listen_port) llerrs << "problem loading eventhost plugin, status: " << status << llendl; } - // Store the handle and link it to the pool that was used to allocate it. - mPlugins[eventhost_dso_handle] = eventhost_dso_memory_pool_ptr; + mPlugins.insert(eventhost_dso_handle); } void LLAppViewer::launchUpdater() diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 168aaf5d94..71a7868191 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -270,7 +270,7 @@ private: LLAllocator mAlloc; - std::map<apr_dso_handle_t*, boost::shared_ptr<LLAPRPool> > mPlugins; + std::set<struct apr_dso_handle_t*> mPlugins; LLFrameTimer mMemCheckTimer; diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index db11462fcb..48d02dfeaa 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -111,7 +111,6 @@ int main( int argc, char **argv ) } delete viewer_app_ptr; viewer_app_ptr = NULL; - return 0; } diff --git a/indra/newview/llappviewerlinux_api_dbus.cpp b/indra/newview/llappviewerlinux_api_dbus.cpp index 1ae469dfcf..32e7e0a83d 100644 --- a/indra/newview/llappviewerlinux_api_dbus.cpp +++ b/indra/newview/llappviewerlinux_api_dbus.cpp @@ -27,11 +27,11 @@ #if LL_DBUS_ENABLED #include "linden_common.h" -#include "llaprpool.h" extern "C" { #include <dbus/dbus-glib.h> +#include "apr_pools.h" #include "apr_dso.h" } @@ -44,7 +44,7 @@ extern "C" { #undef LL_DBUS_SYM static bool sSymsGrabbed = false; -static LLAPRPool sSymDBUSDSOMemoryPool; +static apr_pool_t *sSymDBUSDSOMemoryPool = NULL; static apr_dso_handle_t *sSymDBUSDSOHandleG = NULL; bool grab_dbus_syms(std::string dbus_dso_name) @@ -63,11 +63,11 @@ bool grab_dbus_syms(std::string dbus_dso_name) #define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##DBUSSYM, sSymDBUSDSOHandle, #DBUSSYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #DBUSSYM); if (REQUIRED) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #DBUSSYM, (void*)ll##DBUSSYM);}while(0) //attempt to load the shared library - sSymDBUSDSOMemoryPool.create(); + apr_pool_create(&sSymDBUSDSOMemoryPool, NULL); if ( APR_SUCCESS == (rv = apr_dso_load(&sSymDBUSDSOHandle, dbus_dso_name.c_str(), - sSymDBUSDSOMemoryPool()) )) + sSymDBUSDSOMemoryPool) )) { INFOMSG("Found DSO: %s", dbus_dso_name.c_str()); @@ -109,7 +109,11 @@ void ungrab_dbus_syms() sSymDBUSDSOHandleG = NULL; } - sSymDBUSDSOMemoryPool.destroy(); + if ( sSymDBUSDSOMemoryPool ) + { + apr_pool_destroy(sSymDBUSDSOMemoryPool); + sSymDBUSDSOMemoryPool = NULL; + } // NULL-out all of the symbols we'd grabbed #define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) do{ll##DBUSSYM = NULL;}while(0) diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 8929c0c1a4..c2916717bd 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -113,7 +113,6 @@ int main( int argc, char **argv ) } delete viewer_app_ptr; viewer_app_ptr = NULL; - return 0; } diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp index 9f0218a95e..1f334815d6 100644 --- a/indra/newview/llfloateranimpreview.cpp +++ b/indra/newview/llfloateranimpreview.cpp @@ -223,7 +223,8 @@ BOOL LLFloaterAnimPreview::postBuild() // now load bvh file S32 file_size; - LLAPRFile infile(mFilenameAndPath, LL_APR_RB, &file_size); + LLAPRFile infile ; + infile.open(mFilenameAndPath, LL_APR_RB, NULL, &file_size); if (!infile.getFileHandle()) { diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 5869cf6fee..881f087d7b 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -388,7 +388,7 @@ mCalculateBtn(NULL) mLastMouseX = 0; mLastMouseY = 0; mGLName = 0; - mStatusLock = new LLMutex(); + mStatusLock = new LLMutex(NULL); mModelPreview = NULL; mLODMode[LLModel::LOD_HIGH] = 0; @@ -3077,7 +3077,7 @@ LLColor4 LLModelLoader::getDaeColor(daeElement* element) //----------------------------------------------------------------------------- LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp) -: LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE), LLMutex() +: LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE), LLMutex(NULL) , mPelvisZOffset( 0.0f ) , mLegacyRigValid( false ) , mRigValidJointUpload( false ) diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index ceba4a0191..9db175ec2e 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -202,6 +202,7 @@ void LLInventoryFetchItemsObserver::changed(U32 mask) void fetch_items_from_llsd(const LLSD& items_llsd) { if (!items_llsd.size() || gDisconnected) return; + LLSD body; body[0]["cap_name"] = "FetchInventory2"; body[1]["cap_name"] = "FetchLib2"; @@ -212,7 +213,7 @@ void fetch_items_from_llsd(const LLSD& items_llsd) body[0]["items"].append(items_llsd[i]); continue; } - if (items_llsd[i]["owner_id"].asString() == ALEXANDRIA_LINDEN_ID.asString()) + else if (items_llsd[i]["owner_id"].asString() == ALEXANDRIA_LINDEN_ID.asString()) { body[1]["items"].append(items_llsd[i]); continue; @@ -221,19 +222,23 @@ void fetch_items_from_llsd(const LLSD& items_llsd) for (S32 i=0; i<body.size(); i++) { - if(!gAgent.getRegion()) + if (!gAgent.getRegion()) { - llwarns<<"Agent's region is null"<<llendl; + llwarns << "Agent's region is null" << llendl; break; } - if (0 >= body[i].size()) continue; - std::string url = gAgent.getRegion()->getCapability(body[i]["cap_name"].asString()); + if (0 == body[i]["items"].size()) { + lldebugs << "Skipping body with no items to fetch" << llendl; + continue; + } + + std::string url = gAgent.getRegion()->getCapability(body[i]["cap_name"].asString()); if (!url.empty()) { body[i]["agent_id"] = gAgent.getID(); LLHTTPClient::post(url, body[i], new LLInventoryModel::fetchInventoryResponder(body[i])); - break; + continue; } LLMessageSystem* msg = gMessageSystem; @@ -303,7 +308,7 @@ void LLInventoryFetchItemsObserver::startFetch() // It's incomplete, so put it on the incomplete container, and // pack this on the message. mIncomplete.push_back(*it); - + // Prepare the data to fetch LLSD item_entry; item_entry["owner_id"] = owner_id; diff --git a/indra/newview/llmainlooprepeater.cpp b/indra/newview/llmainlooprepeater.cpp index d73048a28b..5c020e6d98 100644 --- a/indra/newview/llmainlooprepeater.cpp +++ b/indra/newview/llmainlooprepeater.cpp @@ -46,7 +46,7 @@ void LLMainLoopRepeater::start(void) { if(mQueue != 0) return; - mQueue = new LLThreadSafeQueue<LLSD>(1024); + mQueue = new LLThreadSafeQueue<LLSD>(gAPRPoolp, 1024); mMainLoopConnection = LLEventPumps::instance(). obtain("mainloop").listen(LLEventPump::inventName(), boost::bind(&LLMainLoopRepeater::onMainLoop, this, _1)); mRepeaterConnection = LLEventPumps::instance(). diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index e12f140747..a97e256c89 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -447,9 +447,9 @@ LLMeshRepoThread::LLMeshRepoThread() : LLThread("mesh repo") { mWaiting = false; - mMutex = new LLMutex(); - mHeaderMutex = new LLMutex(); - mSignal = new LLCondition(); + mMutex = new LLMutex(NULL); + mHeaderMutex = new LLMutex(NULL); + mSignal = new LLCondition(NULL); } LLMeshRepoThread::~LLMeshRepoThread() @@ -1198,7 +1198,7 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data, mUploadTextures = upload_textures; mUploadSkin = upload_skin; mUploadJoints = upload_joints; - mMutex = new LLMutex(); + mMutex = new LLMutex(NULL); mCurlRequest = NULL; mPendingUploads = 0; mFinished = false; @@ -2043,7 +2043,7 @@ LLMeshRepository::LLMeshRepository() void LLMeshRepository::init() { - mMeshMutex = new LLMutex(); + mMeshMutex = new LLMutex(NULL); LLConvexDecomposition::getInstance()->initSystem(); @@ -2866,8 +2866,8 @@ LLPhysicsDecomp::LLPhysicsDecomp() mQuitting = false; mDone = false; - mSignal = new LLCondition(); - mMutex = new LLMutex(); + mSignal = new LLCondition(NULL); + mMutex = new LLMutex(NULL); } LLPhysicsDecomp::~LLPhysicsDecomp() diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 749acea6c1..1795be91b9 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2387,13 +2387,6 @@ void asset_callback_nothing(LLVFS*, const LLUUID&, LLAssetType::EType, void*, S3 // nothing } -// *HACK: Must match name in Library or agent inventory -const std::string ROOT_GESTURES_FOLDER = "Gestures"; -const std::string COMMON_GESTURES_FOLDER = "Common Gestures"; -const std::string MALE_GESTURES_FOLDER = "Male Gestures"; -const std::string FEMALE_GESTURES_FOLDER = "Female Gestures"; -const std::string SPEECH_GESTURES_FOLDER = "Speech Gestures"; -const std::string OTHER_GESTURES_FOLDER = "Other Gestures"; const S32 OPT_CLOSED_WINDOW = -1; const S32 OPT_MALE = 0; const S32 OPT_FEMALE = 1; @@ -2422,84 +2415,30 @@ bool callback_choose_gender(const LLSD& notification, const LLSD& response) return false; } -void LLStartUp::copyLibraryGestures(const std::string& same_gender_gestures) -{ - llinfos << "Copying library gestures" << llendl; - - // Copy gestures - LLUUID lib_gesture_cat_id = - gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE,false,true); - if (lib_gesture_cat_id.isNull()) - { - llwarns << "Unable to copy gestures, source category not found" << llendl; - } - LLUUID dst_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE); - - std::vector<std::string> gesture_folders_to_copy; - gesture_folders_to_copy.push_back(MALE_GESTURES_FOLDER); - gesture_folders_to_copy.push_back(FEMALE_GESTURES_FOLDER); - gesture_folders_to_copy.push_back(COMMON_GESTURES_FOLDER); - gesture_folders_to_copy.push_back(SPEECH_GESTURES_FOLDER); - gesture_folders_to_copy.push_back(OTHER_GESTURES_FOLDER); - - for(std::vector<std::string>::iterator it = gesture_folders_to_copy.begin(); - it != gesture_folders_to_copy.end(); - ++it) - { - std::string& folder_name = *it; - - LLPointer<LLInventoryCallback> cb(NULL); - - if (folder_name == same_gender_gestures || - folder_name == COMMON_GESTURES_FOLDER || - folder_name == OTHER_GESTURES_FOLDER) - { - cb = new ActivateGestureCallback; - } - - - LLUUID cat_id = findDescendentCategoryIDByName(lib_gesture_cat_id,folder_name); - if (cat_id.isNull()) - { - llwarns << "failed to find gesture folder for " << folder_name << llendl; - } - else - { - llinfos << "initiating fetch and copy for " << folder_name << " cat_id " << cat_id << llendl; - LLAppearanceMgr* app_mgr = LLAppearanceMgr::getInstance(); - callAfterCategoryFetch(cat_id, - boost::bind(&LLAppearanceMgr::shallowCopyCategory, - app_mgr, - cat_id, - dst_id, - cb)); - } - } -} - void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name, const std::string& gender_name ) { - llinfos << "starting" << llendl; + lldebugs << "starting" << llendl; // Not going through the processAgentInitialWearables path, so need to set this here. LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true); // Initiate creation of COF, since we're also bypassing that. gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - S32 gender = 0; - std::string same_gender_gestures; + ESex gender; if (gender_name == "male") { - gender = OPT_MALE; - same_gender_gestures = MALE_GESTURES_FOLDER; + lldebugs << "male" << llendl; + gender = SEX_MALE; } else { - gender = OPT_FEMALE; - same_gender_gestures = FEMALE_GESTURES_FOLDER; + lldebugs << "female" << llendl; + gender = SEX_FEMALE; } + gAgentAvatarp->setSex(gender); + // try to find the outfit - if not there, create some default // wearables. LLUUID cat_id = findDescendentCategoryIDByName( @@ -2507,7 +2446,8 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name, outfit_folder_name); if (cat_id.isNull()) { - gAgentWearables.createStandardWearables(gender); + lldebugs << "standard wearables" << llendl; + gAgentWearables.createStandardWearables(); } else { @@ -2517,26 +2457,28 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name, bool do_append = false; LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); LLAppearanceMgr::instance().wearInventoryCategory(cat, do_copy, do_append); + lldebugs << "initial outfit category id: " << cat_id << llendl; } - // Copy gestures - copyLibraryGestures(same_gender_gestures); - // This is really misnamed -- it means we have started loading // an outfit/shape that will give the avatar a gender eventually. JC gAgent.setGenderChosen(TRUE); - } //static void LLStartUp::saveInitialOutfit() { - if (sInitialOutfit.empty()) return; + if (sInitialOutfit.empty()) { + lldebugs << "sInitialOutfit is empty" << llendl; + return; + } if (sWearablesLoadedCon.connected()) { + lldebugs << "sWearablesLoadedCon is connected, disconnecting" << llendl; sWearablesLoadedCon.disconnect(); } + lldebugs << "calling makeNewOutfitLinks( \"" << sInitialOutfit << "\" )" << llendl; LLAppearanceMgr::getInstance()->makeNewOutfitLinks(sInitialOutfit,false); } @@ -3340,8 +3282,6 @@ bool process_login_success_response() } // Initial outfit for the user. - // QUESTION: Why can't we simply simply set the users outfit directly - // from a web page into the user info on the server? - Roxie LLSD initial_outfit = response["initial-outfit"][0]; if(initial_outfit.size()) { diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index 99a644eb9c..0a18ef1b2d 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -90,8 +90,6 @@ public: static void initNameCache(); - static void copyLibraryGestures(const std::string& same_gender_gestures); - static void cleanupNameCache(); // outfit_folder_name can be a folder anywhere in your inventory, diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 87b6304f9d..70b0a31308 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -36,6 +36,7 @@ // Included to allow LLTextureCache::purgeTextures() to pause watchdog timeout #include "llappviewer.h" +#include "llmemory.h" // Cache organization: // cache/texture.entries @@ -176,7 +177,7 @@ private: bool LLTextureCacheLocalFileWorker::doRead() { - S32 local_size = LLAPRFile::size(mFileName); + S32 local_size = LLAPRFile::size(mFileName, mCache->getLocalAPRFilePool()); if (local_size > 0 && mFileName.size() > 4) { @@ -250,7 +251,7 @@ bool LLTextureCacheLocalFileWorker::doRead() } mReadData = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), mDataSize); - S32 bytes_read = LLAPRFile::readEx(mFileName, mReadData, mOffset, mDataSize); + S32 bytes_read = LLAPRFile::readEx(mFileName, mReadData, mOffset, mDataSize, mCache->getLocalAPRFilePool()); if (bytes_read != mDataSize) { @@ -331,7 +332,7 @@ bool LLTextureCacheRemoteWorker::doRead() // Is it a JPEG2000 file? { local_filename = filename + ".j2c"; - local_size = LLAPRFile::size(local_filename); + local_size = LLAPRFile::size(local_filename, mCache->getLocalAPRFilePool()); if (local_size > 0) { mImageFormat = IMG_CODEC_J2C; @@ -341,7 +342,7 @@ bool LLTextureCacheRemoteWorker::doRead() if (local_size == 0) { local_filename = filename + ".jpg"; - local_size = LLAPRFile::size(local_filename); + local_size = LLAPRFile::size(local_filename, mCache->getLocalAPRFilePool()); if (local_size > 0) { mImageFormat = IMG_CODEC_JPEG; @@ -352,7 +353,7 @@ bool LLTextureCacheRemoteWorker::doRead() if (local_size == 0) { local_filename = filename + ".tga"; - local_size = LLAPRFile::size(local_filename); + local_size = LLAPRFile::size(local_filename, mCache->getLocalAPRFilePool()); if (local_size > 0) { mImageFormat = IMG_CODEC_TGA; @@ -378,7 +379,8 @@ bool LLTextureCacheRemoteWorker::doRead() } // Allocate read buffer mReadData = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), mDataSize); - S32 bytes_read = LLAPRFile::readEx(local_filename, mReadData, mOffset, mDataSize); + S32 bytes_read = LLAPRFile::readEx(local_filename, + mReadData, mOffset, mDataSize, mCache->getLocalAPRFilePool()); if (bytes_read != mDataSize) { llwarns << "Error reading file from local cache: " << local_filename @@ -429,7 +431,8 @@ bool LLTextureCacheRemoteWorker::doRead() size = llmin(size, mDataSize); // Allocate the read buffer mReadData = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), size); - S32 bytes_read = LLAPRFile::readEx(mCache->mHeaderDataFileName, mReadData, offset, size); + S32 bytes_read = LLAPRFile::readEx(mCache->mHeaderDataFileName, + mReadData, offset, size, mCache->getLocalAPRFilePool()); if (bytes_read != size) { llwarns << "LLTextureCacheWorker: " << mID @@ -455,7 +458,7 @@ bool LLTextureCacheRemoteWorker::doRead() if (!done && (mState == BODY)) { std::string filename = mCache->getTextureFileName(mID); - S32 filesize = LLAPRFile::size(filename); + S32 filesize = LLAPRFile::size(filename, mCache->getLocalAPRFilePool()); if (filesize && (filesize + TEXTURE_CACHE_ENTRY_SIZE) > mOffset) { @@ -497,7 +500,8 @@ bool LLTextureCacheRemoteWorker::doRead() // Read the data at last S32 bytes_read = LLAPRFile::readEx(filename, mReadData + data_offset, - file_offset, file_size); + file_offset, file_size, + mCache->getLocalAPRFilePool()); if (bytes_read != file_size) { llwarns << "LLTextureCacheWorker: " << mID @@ -598,13 +602,13 @@ bool LLTextureCacheRemoteWorker::doWrite() U8* padBuffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), TEXTURE_CACHE_ENTRY_SIZE); memset(padBuffer, 0, TEXTURE_CACHE_ENTRY_SIZE); // Init with zeros memcpy(padBuffer, mWriteData, mDataSize); // Copy the write buffer - bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, padBuffer, offset, size); + bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, padBuffer, offset, size, mCache->getLocalAPRFilePool()); FREE_MEM(LLImageBase::getPrivatePool(), padBuffer); } else { // Write the header record (== first TEXTURE_CACHE_ENTRY_SIZE bytes of the raw file) in the header file - bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, mWriteData, offset, size); + bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, mWriteData, offset, size, mCache->getLocalAPRFilePool()); } if (bytes_written <= 0) @@ -639,7 +643,8 @@ bool LLTextureCacheRemoteWorker::doWrite() // llinfos << "Writing Body: " << filename << " Bytes: " << file_offset+file_size << llendl; S32 bytes_written = LLAPRFile::writeEx( filename, mWriteData + TEXTURE_CACHE_ENTRY_SIZE, - 0, file_size); + 0, file_size, + mCache->getLocalAPRFilePool()); if (bytes_written <= 0) { llwarns << "LLTextureCacheWorker: " << mID @@ -736,6 +741,9 @@ void LLTextureCacheWorker::endWork(S32 param, bool aborted) LLTextureCache::LLTextureCache(bool threaded) : LLWorkerThread("TextureCache", threaded), + mWorkersMutex(NULL), + mHeaderMutex(NULL), + mListMutex(NULL), mHeaderAPRFile(NULL), mReadOnly(TRUE), //do not allow to change the texture cache until setReadOnly() is called. mTexturesSizeTotal(0), @@ -839,7 +847,7 @@ BOOL LLTextureCache::isInLocal(const LLUUID& id) // Is it a JPEG2000 file? { local_filename = filename + ".j2c"; - local_size = LLAPRFile::size(local_filename); + local_size = LLAPRFile::size(local_filename, getLocalAPRFilePool()); if (local_size > 0) { return TRUE ; @@ -849,7 +857,7 @@ BOOL LLTextureCache::isInLocal(const LLUUID& id) // If not, is it a jpeg file? { local_filename = filename + ".jpg"; - local_size = LLAPRFile::size(local_filename); + local_size = LLAPRFile::size(local_filename, getLocalAPRFilePool()); if (local_size > 0) { return TRUE ; @@ -859,7 +867,7 @@ BOOL LLTextureCache::isInLocal(const LLUUID& id) // Hmm... What about a targa file? (used for UI texture mostly) { local_filename = filename + ".tga"; - local_size = LLAPRFile::size(local_filename); + local_size = LLAPRFile::size(local_filename, getLocalAPRFilePool()); if (local_size > 0) { return TRUE ; @@ -905,10 +913,10 @@ void LLTextureCache::purgeCache(ELLPath location) if(LLFile::isdir(mTexturesDirName)) { std::string file_name = gDirUtilp->getExpandedFilename(location, entries_filename); - LLAPRFile::remove(file_name); + LLAPRFile::remove(file_name, getLocalAPRFilePool()); file_name = gDirUtilp->getExpandedFilename(location, cache_filename); - LLAPRFile::remove(file_name); + LLAPRFile::remove(file_name, getLocalAPRFilePool()); purgeAllTextures(true); } @@ -984,9 +992,7 @@ LLAPRFile* LLTextureCache::openHeaderEntriesFile(bool readonly, S32 offset) { llassert_always(mHeaderAPRFile == NULL); apr_int32_t flags = readonly ? APR_READ|APR_BINARY : APR_READ|APR_WRITE|APR_BINARY; - // All code calling openHeaderEntriesFile, immediately calls closeHeaderEntriesFile, - // so this file is very short-lived. - mHeaderAPRFile = new LLAPRFile(mHeaderEntriesFileName, flags); + mHeaderAPRFile = new LLAPRFile(mHeaderEntriesFileName, flags, getLocalAPRFilePool()); if(offset > 0) { mHeaderAPRFile->seek(APR_SET, offset); @@ -1009,9 +1015,10 @@ void LLTextureCache::readEntriesHeader() { // mHeaderEntriesInfo initializes to default values so safe not to read it llassert_always(mHeaderAPRFile == NULL); - if (LLAPRFile::isExist(mHeaderEntriesFileName)) + if (LLAPRFile::isExist(mHeaderEntriesFileName, getLocalAPRFilePool())) { - LLAPRFile::readEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo)); + LLAPRFile::readEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo), + getLocalAPRFilePool()); } else //create an empty entries header. { @@ -1026,7 +1033,8 @@ void LLTextureCache::writeEntriesHeader() llassert_always(mHeaderAPRFile == NULL); if (!mReadOnly) { - LLAPRFile::writeEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo)); + LLAPRFile::writeEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo), + getLocalAPRFilePool()); } } @@ -1615,7 +1623,7 @@ void LLTextureCache::purgeTextures(bool validate) if (uuididx == validate_idx) { LL_DEBUGS("TextureCache") << "Validating: " << filename << "Size: " << entries[idx].mBodySize << LL_ENDL; - S32 bodysize = LLAPRFile::size(filename); + S32 bodysize = LLAPRFile::size(filename, getLocalAPRFilePool()); if (bodysize != entries[idx].mBodySize) { LL_WARNS("TextureCache") << "TEXTURE CACHE BODY HAS BAD SIZE: " << bodysize << " != " << entries[idx].mBodySize @@ -1850,7 +1858,7 @@ void LLTextureCache::removeCachedTexture(const LLUUID& id) mTexturesSizeMap.erase(id); } mHeaderIDMap.erase(id); - LLAPRFile::remove(getTextureFileName(id)); + LLAPRFile::remove(getTextureFileName(id), getLocalAPRFilePool()); } //called after mHeaderMutex is locked. @@ -1862,7 +1870,7 @@ void LLTextureCache::removeEntry(S32 idx, Entry& entry, std::string& filename) { if (entry.mBodySize == 0) // Always attempt to remove when mBodySize > 0. { - if (LLAPRFile::isExist(filename)) // Sanity check. Shouldn't exist when body size is 0. + if (LLAPRFile::isExist(filename, getLocalAPRFilePool())) // Sanity check. Shouldn't exist when body size is 0. { LL_WARNS("TextureCache") << "Entry has body size of zero but file " << filename << " exists. Deleting this file, too." << LL_ENDL; } @@ -1883,7 +1891,7 @@ void LLTextureCache::removeEntry(S32 idx, Entry& entry, std::string& filename) if (file_maybe_exists) { - LLAPRFile::remove(filename); + LLAPRFile::remove(filename, getLocalAPRFilePool()); } } diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h index 79f5ba5835..64e3a2658c 100644 --- a/indra/newview/lltexturecache.h +++ b/indra/newview/lltexturecache.h @@ -142,6 +142,9 @@ protected: std::string getTextureFileName(const LLUUID& id); void addCompleted(Responder* responder, bool success); +protected: + //void setFileAPRPool(apr_pool_t* pool) { mFileAPRPool = pool ; } + private: void setDirNames(ELLPath location); void readHeaderCache(); diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index e9be45ffd0..56dfb61c4f 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -674,6 +674,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mRetryAttempt(0), mActiveCount(0), mGetStatus(0), + mWorkMutex(NULL), mFirstPacket(0), mLastPacket(-1), mTotalPackets(0), @@ -1810,11 +1811,13 @@ bool LLTextureFetchWorker::writeToCacheComplete() // public LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* imagedecodethread, bool threaded, bool qa_mode) - : LLWorkerThread("TextureFetch", threaded), + : LLWorkerThread("TextureFetch", threaded, true), mDebugCount(0), mDebugPause(FALSE), mPacketCount(0), mBadPacketCount(0), + mQueueMutex(getAPRPool()), + mNetworkQueueMutex(getAPRPool()), mTextureCache(cache), mImageDecodeThread(imagedecodethread), mTextureBandwidth(0), diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 6142ee0dd6..19326c4e30 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -202,7 +202,7 @@ void display_stats() gMemoryAllocated = LLMemory::getCurrentRSS(); U32 memory = (U32)(gMemoryAllocated / (1024*1024)); llinfos << llformat("MEMORY: %d MB", memory) << llendl; - LLMemory::logMemoryInfo() ; + LLMemory::logMemoryInfo(TRUE) ; gRecentMemoryTime.reset(); } } diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 8139f7deda..b9293b3b31 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -149,7 +149,7 @@ void LLFilePickerThread::run() //static void LLFilePickerThread::initClass() { - sMutex = new LLMutex(); + sMutex = new LLMutex(NULL); } //static @@ -816,7 +816,8 @@ LLUUID upload_new_resource( uuid = tid.makeAssetID(gAgent.getSecureSessionID()); // copy this file into the vfs for upload S32 file_size; - LLAPRFile infile(filename, LL_APR_RB, &file_size); + LLAPRFile infile ; + infile.open(filename, LL_APR_RB, NULL, &file_size); if (infile.getFileHandle()) { LLVFile file(gVFS, uuid, asset_type, LLVFile::WRITE); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index e457cc3e70..bdab250b49 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -7524,7 +7524,8 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) // static void LLVOAvatar::dumpArchetypeXML( void* ) { - LLAPRFile outfile(gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER, "new archetype.xml"), LL_APR_WB); + LLAPRFile outfile; + outfile.open(gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,"new archetype.xml"), LL_APR_WB ); apr_file_t* file = outfile.getFileHandle() ; if (!file) { diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index baf01ec066..7db19c5c1b 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -268,6 +268,7 @@ LLVOCache::LLVOCache(): mCacheSize(1) { mEnabled = gSavedSettings.getBOOL("ObjectCacheEnabled"); + mLocalAPRFilePoolp = new LLVolatileAPRPool() ; } LLVOCache::~LLVOCache() @@ -277,6 +278,7 @@ LLVOCache::~LLVOCache() writeCacheHeader(); clearCacheInMemory(); } + delete mLocalAPRFilePoolp; } void LLVOCache::setDirNames(ELLPath location) @@ -433,7 +435,7 @@ void LLVOCache::removeFromCache(HeaderEntryInfo* entry) std::string filename; getObjectCacheFilename(entry->mHandle, filename); - LLAPRFile::remove(filename); + LLAPRFile::remove(filename, mLocalAPRFilePoolp); entry->mTime = INVALID_TIME ; updateEntry(entry) ; //update the head file. } @@ -450,9 +452,9 @@ void LLVOCache::readCacheHeader() clearCacheInMemory(); bool success = true ; - if (LLAPRFile::isExist(mHeaderFileName)) + if (LLAPRFile::isExist(mHeaderFileName, mLocalAPRFilePoolp)) { - LLAPRFile apr_file(mHeaderFileName, APR_READ|APR_BINARY); + LLAPRFile apr_file(mHeaderFileName, APR_READ|APR_BINARY, mLocalAPRFilePoolp); //read the meta element success = check_read(&apr_file, &mMetaInfo, sizeof(HeaderMetaInfo)) ; @@ -537,7 +539,7 @@ void LLVOCache::writeCacheHeader() bool success = true ; { - LLAPRFile apr_file(mHeaderFileName, APR_CREATE|APR_WRITE|APR_BINARY); + LLAPRFile apr_file(mHeaderFileName, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); //write the meta element success = check_write(&apr_file, &mMetaInfo, sizeof(HeaderMetaInfo)) ; @@ -575,7 +577,7 @@ void LLVOCache::writeCacheHeader() BOOL LLVOCache::updateEntry(const HeaderEntryInfo* entry) { - LLAPRFile apr_file(mHeaderFileName, APR_WRITE|APR_BINARY); + LLAPRFile apr_file(mHeaderFileName, APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); apr_file.seek(APR_SET, entry->mIndex * sizeof(HeaderEntryInfo) + sizeof(HeaderMetaInfo)) ; return check_write(&apr_file, (void*)entry, sizeof(HeaderEntryInfo)) ; @@ -601,7 +603,7 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca { std::string filename; getObjectCacheFilename(handle, filename); - LLAPRFile apr_file(filename, APR_READ|APR_BINARY); + LLAPRFile apr_file(filename, APR_READ|APR_BINARY, mLocalAPRFilePoolp); LLUUID cache_id ; success = check_read(&apr_file, cache_id.mData, UUID_BYTES) ; @@ -724,7 +726,7 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: { std::string filename; getObjectCacheFilename(handle, filename); - LLAPRFile apr_file(filename, APR_CREATE|APR_WRITE|APR_BINARY); + LLAPRFile apr_file(filename, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); success = check_write(&apr_file, (void*)id.mData, UUID_BYTES) ; diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h index 13651c6779..14e3b4c793 100644 --- a/indra/newview/llvocache.h +++ b/indra/newview/llvocache.h @@ -142,6 +142,7 @@ private: U32 mNumEntries; std::string mHeaderFileName ; std::string mObjectCacheDirName; + LLVolatileAPRPool* mLocalAPRFilePoolp ; header_entry_queue_t mHeaderEntryQueue; handle_entry_map_t mHandleEntryMap; diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 90a05cd9e5..56d71e96b3 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -942,7 +942,7 @@ void LLVivoxVoiceClient::stateMachine() if(!mSocket) { - mSocket = LLSocket::create(LLSocket::STREAM_TCP); + mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); } mConnected = mSocket->blockingConnect(mDaemonHost); diff --git a/indra/newview/llwatchdog.cpp b/indra/newview/llwatchdog.cpp index 64ca94b567..4f582fc2db 100644 --- a/indra/newview/llwatchdog.cpp +++ b/indra/newview/llwatchdog.cpp @@ -178,8 +178,8 @@ void LLWatchdog::init(killer_event_callback func) mKillerCallback = func; if(!mSuspectsAccessMutex && !mTimer) { - mSuspectsAccessMutex = new LLMutex; - mTimer = new LLWatchdogTimerThread; + mSuspectsAccessMutex = new LLMutex(NULL); + mTimer = new LLWatchdogTimerThread(); mTimer->setSleepTime(WATCHDOG_SLEEP_TIME_USEC / 1000); mLastClockCount = LLTimer::getTotalTime(); diff --git a/indra/newview/tests/llworldmap_test.cpp b/indra/newview/tests/llworldmap_test.cpp index 102294959a..acc6e814bc 100644 --- a/indra/newview/tests/llworldmap_test.cpp +++ b/indra/newview/tests/llworldmap_test.cpp @@ -27,6 +27,7 @@ // Dependencies #include "linden_common.h" +#include "llapr.h" #include "llsingleton.h" #include "lltrans.h" #include "lluistring.h" diff --git a/indra/test/lltemplatemessagebuilder_tut.cpp b/indra/test/lltemplatemessagebuilder_tut.cpp index 532f26ee60..09beb53869 100644 --- a/indra/test/lltemplatemessagebuilder_tut.cpp +++ b/indra/test/lltemplatemessagebuilder_tut.cpp @@ -29,6 +29,7 @@ #include "linden_common.h" #include "lltut.h" +#include "llapr.h" #include "llmessagetemplate.h" #include "llquaternion.h" #include "lltemplatemessagebuilder.h" @@ -52,6 +53,7 @@ namespace tut static bool init = false; if(! init) { + ll_init_apr(); const F32 circuit_heartbeat_interval=5; const F32 circuit_timeout=100; diff --git a/indra/test/message_tut.cpp b/indra/test/message_tut.cpp index 9a6ccd4d68..d971b33475 100644 --- a/indra/test/message_tut.cpp +++ b/indra/test/message_tut.cpp @@ -29,6 +29,7 @@ #include "linden_common.h" #include "lltut.h" +#include "llapr.h" #include "llmessageconfig.h" #include "llsdserialize.h" #include "llversionserver.h" @@ -61,6 +62,7 @@ namespace tut static bool init = false; if(!init) { + ll_init_apr(); //init_prehash_data(); init = true; } diff --git a/indra/test/test.cpp b/indra/test/test.cpp index 45e8aef99a..ffdb0cb976 100644 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -37,8 +37,8 @@ #include "linden_common.h" #include "llerrorcontrol.h" #include "lltut.h" -#include "llaprpool.h" +#include "apr_pools.h" #include "apr_getopt.h" // the CTYPE_WORKAROUND is needed for linux dev stations that don't @@ -349,12 +349,17 @@ int main(int argc, char **argv) ctype_workaround(); #endif - LLAPRPool pool; - pool.create(); + apr_initialize(); + apr_pool_t* pool = NULL; + if(APR_SUCCESS != apr_pool_create(&pool, NULL)) + { + std::cerr << "Unable to initialize pool" << std::endl; + return 1; + } apr_getopt_t* os = NULL; - if(APR_SUCCESS != apr_getopt_init(&os, pool(), argc, argv)) + if(APR_SUCCESS != apr_getopt_init(&os, pool, argc, argv)) { - std::cerr << "Unable to initialize the arguments for parsing by apr_getopt()." << std::endl; + std::cerr << "Unable to pool" << std::endl; return 1; } @@ -472,6 +477,8 @@ int main(int argc, char **argv) s.close(); } + apr_terminate(); + int retval = (success ? 0 : 1); return retval; diff --git a/indra/test_apps/llplugintest/llmediaplugintest.cpp b/indra/test_apps/llplugintest/llmediaplugintest.cpp index d5ee09c5bc..884b00f0cc 100644 --- a/indra/test_apps/llplugintest/llmediaplugintest.cpp +++ b/indra/test_apps/llplugintest/llmediaplugintest.cpp @@ -27,6 +27,7 @@ #include "linden_common.h" #include "indra_constants.h" +#include "llapr.h" #include "llerrorcontrol.h" #include <math.h> @@ -185,6 +186,9 @@ LLMediaPluginTest::LLMediaPluginTest( int app_window, int window_width, int wind std::cout << "Unable to read bookmarks from file: " << bookmarks_filename << std::endl; }; + // initialize linden lab APR module + ll_init_apr(); + // Set up llerror logging { LLError::initForApplication("."); diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp index 24ba00ad8e..c7b70c2de8 100644 --- a/indra/viewer_components/updater/llupdateinstaller.cpp +++ b/indra/viewer_components/updater/llupdateinstaller.cpp @@ -26,7 +26,6 @@ #include "linden_common.h" #include <apr_file_io.h> #include "llapr.h" -#include "llscopedvolatileaprpool.h" #include "llprocesslauncher.h" #include "llupdateinstaller.h" #include "lldir.h" @@ -46,8 +45,7 @@ namespace { { std::string scriptFile = gDirUtilp->getBaseFileName(path); std::string newPath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, scriptFile); - LLScopedVolatileAPRPool pool; - apr_status_t status = apr_file_copy(path.c_str(), newPath.c_str(), APR_FILE_SOURCE_PERMS, pool); + apr_status_t status = apr_file_copy(path.c_str(), newPath.c_str(), APR_FILE_SOURCE_PERMS, gAPRPoolp); if(status != APR_SUCCESS) throw RelocateError(); return newPath; |