Added a thread-safe and robust wrapper for APR pools.

See http://redmine.imprudenceviewer.org/issues/590
and https://jira.secondlife.com/browse/SNOW-596
This commit is contained in:
Aleric Inglewood
2011-05-05 01:34:00 +02:00
parent 5b08560047
commit 4d932d5e2d
57 changed files with 895 additions and 751 deletions

View File

@@ -104,6 +104,7 @@ Aleric Inglewood
IMP-566 IMP-566
IMP-567 IMP-567
IMP-573 IMP-573
IMP-590
IMP-660 IMP-660
IMP-661 IMP-661
IMP-662 IMP-662

View File

@@ -13,6 +13,7 @@ include_directories(
) )
set(llcommon_SOURCE_FILES set(llcommon_SOURCE_FILES
aiaprpool.cpp
imageids.cpp imageids.cpp
indra_constants.cpp indra_constants.cpp
llapp.cpp llapp.cpp
@@ -78,6 +79,7 @@ set(llcommon_SOURCE_FILES
set(llcommon_HEADER_FILES set(llcommon_HEADER_FILES
CMakeLists.txt CMakeLists.txt
aiaprpool.h
bitpack.h bitpack.h
ctype_workaround.h ctype_workaround.h
doublelinkedlist.h doublelinkedlist.h
@@ -155,6 +157,7 @@ set(llcommon_HEADER_FILES
llqueuedthread.h llqueuedthread.h
llrand.h llrand.h
llrun.h llrun.h
llscopedvolatileaprpool.h
llsd.h llsd.h
llsdserialize.h llsdserialize.h
llsdserialize_xml.h llsdserialize_xml.h

View File

@@ -0,0 +1,198 @@
/**
* @file aiaprpool.cpp
*
* Copyright (c) 2010, Aleric Inglewood.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution.
*
* CHANGELOG
* and additional copyright holders.
*
* 04/04/2010
* - Initial version, written by Aleric Inglewood @ SL
*
* 10/11/2010
* - Changed filename, class names and license to a more
* company-neutral format.
* - 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 "aiaprpool.h"
#include "llthread.h"
// Create a subpool from parent.
void AIAPRPool::create(AIAPRPool& 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 = &AIThreadLocalData::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 AIAPRPool::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;
mPool = NULL; // Mark that we are BEING destructed.
apr_pool_cleanup_kill(pool, this, &s_plain_cleanup);
apr_pool_destroy(pool);
}
}
bool AIAPRPool::parent_is_being_destructed(void)
{
return mParent && (!mParent->mPool || mParent->parent_is_being_destructed());
}
AIAPRInitialization::AIAPRInitialization(void)
{
static bool apr_initialized = false;
if (!apr_initialized)
{
apr_initialize();
}
apr_initialized = true;
}
bool AIAPRRootPool::sCountInitialized = false;
apr_uint32_t volatile AIAPRRootPool::sCount;
extern apr_thread_mutex_t* gLogMutexp;
extern apr_thread_mutex_t* gCallStacksLogMutexp;
AIAPRRootPool::AIAPRRootPool(void) : AIAPRInitialization(), AIAPRPool(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 AIAPRRootPool::AIAPRRootPool(void)
// it must be done last, so that sCount is already initialized.
AIThreadLocalData::init();
}
apr_atomic_inc32(&sCount);
}
AIAPRRootPool::~AIAPRRootPool()
{
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 AIAPRRootPool, before terminating APR.
static_cast<AIAPRRootPool*>(this)->destroy();
apr_terminate();
}
}
//static
AIAPRRootPool& AIAPRRootPool::get(void)
{
static AIAPRRootPool global_APRpool(0); // This is what used to be gAPRPoolp.
return global_APRpool;
}
void AIVolatileAPRPool::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)) ;
}

238
indra/llcommon/aiaprpool.h Normal file
View File

@@ -0,0 +1,238 @@
/**
* @file aiaprpool.h
* @brief Implementation of AIAPRPool.
*
* Copyright (c) 2010, Aleric Inglewood.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution.
*
* CHANGELOG
* and additional copyright holders.
*
* 04/04/2010
* - Initial version, written by Aleric Inglewood @ SL
*
* 10/11/2010
* - Changed filename, class names and license to a more
* company-neutral format.
* - Added APR_HAS_THREADS #if's to allow creation and destruction
* of subpools by threads other than the parent pool owner.
*/
#ifndef AIAPRPOOL_H
#define AIAPRPOOL_H
#ifdef LL_WINDOWS
#include <ws2tcpip.h> // Needed before including apr_portable.h
#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 AIAPRPool
{
protected:
apr_pool_t* mPool; //!< Pointer to the underlaying pool. NULL if not initialized.
AIAPRPool* mParent; //!< Pointer to the parent pool, if any. Only valid when mPool is non-zero.
apr_os_thread_t mOwner; //!< The thread that owns this memory pool. Only valid when mPool is non-zero.
public:
//! Construct an uninitialized (destructed) pool.
AIAPRPool(void) : mPool(NULL) { }
//! Construct a subpool from an existing pool.
// This is not a copy-constructor, this class doesn't have one!
AIAPRPool(AIAPRPool& parent) : mPool(NULL) { create(parent); }
//! Destruct the memory pool (free all of it's subpools and allocated memory).
~AIAPRPool() { destroy(); }
protected:
// Create a pool that is allocated from the Operating System. Only used by AIAPRRootPool.
AIAPRPool(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(AIAPRPool& parent = *static_cast<AIAPRPool*>(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 apr_pool_t* const AIAPRPool::* const bool_type;
//! Return true if the pool is initialized.
operator bool_type() const { return mPool ? &AIAPRPool::mPool : 0; }
// Painful, but we have to either provide access to this, or wrap
// every APR function call that needs a apr_pool_t* to be passed.
// NEVER destroy a pool that is returned by this function!
apr_pool_t* operator()(void) const
{
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<AIAPRPool*>(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 it's parents is being destructed.
{
mPool = NULL; // Stop destroy() from destructing the pool again.
}
return APR_SUCCESS;
}
};
class AIAPRInitialization
{
public:
AIAPRInitialization(void);
};
/**
* @brief Root memory pool (allocates memory from the operating system).
*
* This class should only be used by AIThreadLocalData and AIThreadSafeSimpleDCRootPool_pbase
* (and LLMutexRootPool when APR_HAS_THREADS isn't defined).
*/
class LL_COMMON_API AIAPRRootPool : public AIAPRInitialization, public AIAPRPool
{
private:
friend class AIThreadLocalData;
friend class AIThreadSafeSimpleDCRootPool_pbase;
#if !APR_HAS_THREADS
friend class LLMutexRootPool;
#endif
//! Construct a root memory pool.
// Should only be used by AIThreadLocalData and AIThreadSafeSimpleDCRootPool_pbase.
AIAPRRootPool(void);
~AIAPRRootPool();
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 AIThreadLocalData.
// Normally you should not use this. Only use for early initialization
// (before main) and deinitialization (after main).
static AIAPRRootPool& 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 AIAPRRootPool::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 AIAPRRootPool is created before termination
// of the application (which is the case: we create one AIAPRRootPool per thread).
AIAPRRootPool(int) : AIAPRInitialization(), AIAPRPool(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 AIVolatileAPRPool : protected AIAPRPool
{
public:
AIVolatileAPRPool(void) : mNumActiveRef(0), mNumTotalRef(0) { }
apr_pool_t* getVolatileAPRPool(void)
{
if (!mPool) create();
++mNumActiveRef;
++mNumTotalRef;
return AIAPRPool::operator()();
}
void clearVolatileAPRPool(void);
bool isOld(void) const { return mNumTotalRef > FULL_VOLATILE_APR_POOL; }
bool isUnused() const { return mNumActiveRef == 0; }
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 AIVolatileAPRPool until the pool is recreated.
static S32 const FULL_VOLATILE_APR_POOL = 1024;
};
#endif // AIAPRPOOL_H

View File

@@ -123,13 +123,8 @@ void LLApp::commonCtor()
mOptions.append(sd); 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. // Set the application to this instance.
sApplication = this; sApplication = this;
} }
LLApp::LLApp(LLErrorThread *error_thread) : LLApp::LLApp(LLErrorThread *error_thread) :

View File

@@ -34,219 +34,7 @@
#include "linden_common.h" #include "linden_common.h"
#include "llapr.h" #include "llapr.h"
#include "llscopedvolatileaprpool.h"
apr_pool_t *gAPRPoolp = NULL; // Global 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);
// Initialize thread-local APR pool support.
LLVolatileAPRPool::initLocalAPRFilePool();
}
}
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;
}
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 ;
}
}
apr_pool_t* LLAPRPool::getAPRPool()
{
if(!mPool)
{
createAPRPool() ;
}
return mPool ;
}
LLVolatileAPRPool::LLVolatileAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag)
: LLAPRPool(parent, size, releasePoolFlag)
{
mNumActiveRef = 0 ;
mNumTotalRef = 0 ;
}
apr_pool_t* LLVolatileAPRPool::getVolatileAPRPool()
{
mNumTotalRef++ ;
mNumActiveRef++ ;
return getAPRPool() ;
}
void LLVolatileAPRPool::clearVolatileAPRPool()
{
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 ;
}
#ifdef SHOW_ASSERT
// This allows the use of llassert(is_main_thread()) to assure the current thread is the main thread.
static void* gIsMainThread;
bool is_main_thread() { return gIsMainThread == LLVolatileAPRPool::getLocalAPRFilePool(); }
#endif
// The thread private handle to access the LocalAPRFilePool.
apr_threadkey_t* LLVolatileAPRPool::sLocalAPRFilePoolKey;
// This should be called exactly once, before the first call to createLocalAPRFilePool.
// static
void LLVolatileAPRPool::initLocalAPRFilePool()
{
apr_status_t status = apr_threadkey_private_create(&sLocalAPRFilePoolKey, &destroyLocalAPRFilePool, gAPRPoolp);
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 pool for the main thread (this function is called by the main thread).
createLocalAPRFilePool();
#ifdef SHOW_ASSERT
gIsMainThread = getLocalAPRFilePool();
#endif
}
// This should be called once for every thread, before it uses getLocalAPRFilePool.
// static
void LLVolatileAPRPool::createLocalAPRFilePool()
{
void* thread_local_data = new LLVolatileAPRPool;
apr_status_t status = apr_threadkey_private_set(thread_local_data, sLocalAPRFilePoolKey);
llassert_always(status == APR_SUCCESS);
}
// This is called once for every thread when the thread is destructed.
// static
void LLVolatileAPRPool::destroyLocalAPRFilePool(void* thread_local_data)
{
delete reinterpret_cast<LLVolatileAPRPool*>(thread_local_data);
}
// static
LLVolatileAPRPool* LLVolatileAPRPool::getLocalAPRFilePool()
{
void* thread_local_data;
apr_status_t status = apr_threadkey_private_get(&thread_local_data, sLocalAPRFilePoolKey);
llassert_always(status == APR_SUCCESS);
return reinterpret_cast<LLVolatileAPRPool*>(thread_local_data);
}
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// //
@@ -309,13 +97,15 @@ void ll_apr_assert_status(apr_status_t status)
// //
LLAPRFile::LLAPRFile() LLAPRFile::LLAPRFile()
: mFile(NULL), : mFile(NULL),
mCurrentFilePoolp(NULL) mVolatileFilePoolp(NULL),
mRegularFilePoolp(NULL)
{ {
} }
LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, access_t access_type) LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, access_t access_type)
: mFile(NULL), : mFile(NULL),
mCurrentFilePoolp(NULL) mVolatileFilePoolp(NULL),
mRegularFilePoolp(NULL)
{ {
open(filename, flags, access_type); open(filename, flags, access_type);
} }
@@ -334,10 +124,16 @@ apr_status_t LLAPRFile::close()
mFile = NULL ; mFile = NULL ;
} }
if(mCurrentFilePoolp) if (mVolatileFilePoolp)
{ {
mCurrentFilePoolp->clearVolatileAPRPool() ; mVolatileFilePoolp->clearVolatileAPRPool() ;
mCurrentFilePoolp = NULL ; mVolatileFilePoolp = NULL ;
}
if (mRegularFilePoolp)
{
delete mRegularFilePoolp;
mRegularFilePoolp = NULL;
} }
return ret ; return ret ;
@@ -346,25 +142,28 @@ apr_status_t LLAPRFile::close()
apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, access_t access_type, S32* sizep) apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, access_t access_type, S32* sizep)
{ {
llassert_always(!mFile); llassert_always(!mFile);
llassert_always(!mCurrentFilePoolp); llassert_always(!mVolatileFilePoolp && !mRegularFilePoolp);
// Access the pool and increment it's reference count. apr_status_t status;
// The reference count of LLVolatileAPRPool objects will be decremented
// again in LLAPRFile::close by calling mCurrentFilePoolp->clearVolatileAPRPool().
apr_pool_t* pool;
if (access_type == local)
{ {
// Use a "volatile" thread-local pool. apr_pool_t* apr_file_open_pool;
mCurrentFilePoolp = LLVolatileAPRPool::getLocalAPRFilePool(); if (access_type == local)
pool = mCurrentFilePoolp->getVolatileAPRPool(); {
// Use a "volatile" thread-local pool.
mVolatileFilePoolp = &AIThreadLocalData::tldata().mVolatileAPRPool;
// Access the pool and increment it's reference count.
// The reference count of AIVolatileAPRPool objects will be decremented
// again in LLAPRFile::close by calling mVolatileFilePoolp->clearVolatileAPRPool().
apr_file_open_pool = mVolatileFilePoolp->getVolatileAPRPool();
}
else
{
mRegularFilePoolp = new AIAPRPool(AIThreadLocalData::tldata().mRootPool);
apr_file_open_pool = (*mRegularFilePoolp)();
}
status = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, apr_file_open_pool);
} }
else if (status != APR_SUCCESS || !mFile)
{
llassert(is_main_thread());
pool = gAPRPoolp;
}
apr_status_t s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, pool);
if (s != APR_SUCCESS || !mFile)
{ {
mFile = NULL ; mFile = NULL ;
close() ; close() ;
@@ -372,7 +171,7 @@ apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, acc
{ {
*sizep = 0; *sizep = 0;
} }
return s; return status;
} }
if (sizep) if (sizep)
@@ -389,7 +188,7 @@ apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, acc
*sizep = file_size; *sizep = file_size;
} }
return s; return status;
} }
// File I/O // File I/O
@@ -449,17 +248,6 @@ S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset)
//static components of LLAPRFile //static components of LLAPRFile
// //
// Used in the static functions below.
class LLScopedVolatileAPRFilePool {
private:
LLVolatileAPRPool* mPool;
apr_pool_t* apr_pool;
public:
LLScopedVolatileAPRFilePool() : mPool(LLVolatileAPRPool::getLocalAPRFilePool()), apr_pool(mPool->getVolatileAPRPool()) { }
~LLScopedVolatileAPRFilePool() { mPool->clearVolatileAPRPool(); }
operator apr_pool_t*() const { return apr_pool; }
};
//static //static
S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset) S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
{ {
@@ -496,7 +284,7 @@ S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
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)
{ {
apr_file_t* file_handle; apr_file_t* file_handle;
LLScopedVolatileAPRFilePool pool; LLScopedVolatileAPRPool pool;
apr_status_t s = apr_file_open(&file_handle, filename.c_str(), APR_READ|APR_BINARY, APR_OS_DEFAULT, 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) if (s != APR_SUCCESS || !file_handle)
{ {
@@ -548,7 +336,7 @@ S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 n
} }
apr_file_t* file_handle; apr_file_t* file_handle;
LLScopedVolatileAPRFilePool pool; LLScopedVolatileAPRPool pool;
apr_status_t s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool); apr_status_t s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool);
if (s != APR_SUCCESS || !file_handle) if (s != APR_SUCCESS || !file_handle)
{ {
@@ -593,7 +381,7 @@ bool LLAPRFile::remove(const std::string& filename)
{ {
apr_status_t s; apr_status_t s;
LLScopedVolatileAPRFilePool pool; LLScopedVolatileAPRPool pool;
s = apr_file_remove(filename.c_str(), pool); s = apr_file_remove(filename.c_str(), pool);
if (s != APR_SUCCESS) if (s != APR_SUCCESS)
@@ -613,7 +401,7 @@ bool LLAPRFile::rename(const std::string& filename, const std::string& newname)
{ {
apr_status_t s; apr_status_t s;
LLScopedVolatileAPRFilePool pool; LLScopedVolatileAPRPool pool;
s = apr_file_rename(filename.c_str(), newname.c_str(), pool); s = apr_file_rename(filename.c_str(), newname.c_str(), pool);
if (s != APR_SUCCESS) if (s != APR_SUCCESS)
@@ -631,7 +419,7 @@ bool LLAPRFile::isExist(const std::string& filename, apr_int32_t flags)
apr_file_t* file_handle; apr_file_t* file_handle;
apr_status_t s; apr_status_t s;
LLScopedVolatileAPRFilePool pool; LLScopedVolatileAPRPool pool;
s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool); s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool);
if (s != APR_SUCCESS || !file_handle) if (s != APR_SUCCESS || !file_handle)
@@ -652,7 +440,7 @@ S32 LLAPRFile::size(const std::string& filename)
apr_finfo_t info; apr_finfo_t info;
apr_status_t s; apr_status_t s;
LLScopedVolatileAPRFilePool pool; LLScopedVolatileAPRPool pool;
s = apr_file_open(&file_handle, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool); s = apr_file_open(&file_handle, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool);
if (s != APR_SUCCESS || !file_handle) if (s != APR_SUCCESS || !file_handle)
@@ -681,7 +469,7 @@ bool LLAPRFile::makeDir(const std::string& dirname)
{ {
apr_status_t s; apr_status_t s;
LLScopedVolatileAPRFilePool pool; LLScopedVolatileAPRPool pool;
s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool); s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool);
if (s != APR_SUCCESS) if (s != APR_SUCCESS)
@@ -698,7 +486,7 @@ bool LLAPRFile::removeDir(const std::string& dirname)
{ {
apr_status_t s; apr_status_t s;
LLScopedVolatileAPRFilePool pool; LLScopedVolatileAPRPool pool;
s = apr_file_remove(dirname.c_str(), pool); s = apr_file_remove(dirname.c_str(), pool);
if (s != APR_SUCCESS) if (s != APR_SUCCESS)

View File

@@ -48,73 +48,8 @@
#include "apr_atomic.h" #include "apr_atomic.h"
#include "llstring.h" #include "llstring.h"
extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp; class AIAPRPool;
class AIVolatileAPRPool;
/**
* @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) ;
~LLAPRPool() ;
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 : protected LLAPRPool
{
public:
LLVolatileAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE);
~LLVolatileAPRPool(){}
apr_pool_t* getVolatileAPRPool() ;
void clearVolatileAPRPool() ;
BOOL isFull() ;
BOOL isEmpty() {return !mNumActiveRef ;}
static void initLocalAPRFilePool();
static void createLocalAPRFilePool();
static void destroyLocalAPRFilePool(void* thread_local_data);
static LLVolatileAPRPool* getLocalAPRFilePool();
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.
static apr_threadkey_t* sLocalAPRFilePoolKey;
} ;
/** /**
* @class LLScopedLock * @class LLScopedLock
@@ -205,7 +140,8 @@ class LL_COMMON_API LLAPRFile : boost::noncopyable
// make this non copyable since a copy closes the file // make this non copyable since a copy closes the file
private: private:
apr_file_t* mFile ; apr_file_t* mFile ;
LLVolatileAPRPool *mCurrentFilePoolp ; //currently in use apr_pool, could be one of them: sAPRFilePoolp, or a temp pool. AIVolatileAPRPool* mVolatileFilePoolp; // (Thread local) APR pool currently in use.
AIAPRPool* mRegularFilePoolp; // ...or a regular pool.
public: public:
enum access_t { enum access_t {
@@ -260,6 +196,4 @@ bool LL_COMMON_API ll_apr_warn_status(apr_status_t status);
void LL_COMMON_API ll_apr_assert_status(apr_status_t status); void LL_COMMON_API ll_apr_assert_status(apr_status_t status);
extern "C" LL_COMMON_API apr_pool_t* gAPRPoolp; // Global APR memory pool
#endif // LL_LLAPR_H #endif // LL_LLAPR_H

View File

@@ -34,18 +34,10 @@
#include "llcommon.h" #include "llcommon.h"
#include "llthread.h" #include "llthread.h"
//static
BOOL LLCommon::sAprInitialized = FALSE;
//static //static
void LLCommon::initClass() void LLCommon::initClass()
{ {
LLMemory::initClass(); LLMemory::initClass();
if (!sAprInitialized)
{
ll_init_apr();
sAprInitialized = TRUE;
}
LLTimer::initClass(); LLTimer::initClass();
LLThreadSafeRefCount::initThreadSafeRefCount(); LLThreadSafeRefCount::initThreadSafeRefCount();
// LLWorkerThread::initClass(); // LLWorkerThread::initClass();
@@ -59,10 +51,5 @@ void LLCommon::cleanupClass()
// LLWorkerThread::cleanupClass(); // LLWorkerThread::cleanupClass();
LLThreadSafeRefCount::cleanupThreadSafeRefCount(); LLThreadSafeRefCount::cleanupThreadSafeRefCount();
LLTimer::cleanupClass(); LLTimer::cleanupClass();
if (sAprInitialized)
{
ll_cleanup_apr();
sAprInitialized = FALSE;
}
LLMemory::cleanupClass(); LLMemory::cleanupClass();
} }

View File

@@ -43,8 +43,6 @@ class LL_COMMON_API LLCommon
public: public:
static void initClass(); static void initClass();
static void cleanupClass(); static void cleanupClass();
private:
static BOOL sAprInitialized;
}; };
#endif #endif

View File

@@ -877,6 +877,9 @@ You get:
*/ */
apr_thread_mutex_t* gLogMutexp;
apr_thread_mutex_t* gCallStacksLogMutexp;
namespace { namespace {
bool checkLevelMap(const LevelMap& map, const std::string& key, bool checkLevelMap(const LevelMap& map, const std::string& key,
LLError::ELevel& level) LLError::ELevel& level)

View File

@@ -36,8 +36,7 @@
LLFixedBuffer::LLFixedBuffer(const U32 max_lines) LLFixedBuffer::LLFixedBuffer(const U32 max_lines)
: LLLineBuffer(), : LLLineBuffer(),
mMaxLines(max_lines), mMaxLines(max_lines)
mMutex(NULL)
{ {
mTimer.reset(); mTimer.reset();
} }

View File

@@ -0,0 +1,58 @@
/**
* @file llscopedvolatileaprpool.h
* @brief Implementation of LLScopedVolatileAPRPool
*
* $LicenseInfo:firstyear=2010&license=viewergpl$
*
* Copyright (c) 2010, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLSCOPEDVOLATILEAPRPOOL_H
#define LL_LLSCOPEDVOLATILEAPRPOOL_H
#include "llthread.h"
//! Scoped volatile memory pool.
//
// As the AIVolatileAPRPool should never keep allocations very
// long, it's 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 LLScopedVolatileAPRPool
{
private:
AIVolatileAPRPool& mPool;
apr_pool_t* mScopedAPRpool;
public:
LLScopedVolatileAPRPool() : mPool(AIThreadLocalData::tldata().mVolatileAPRPool), mScopedAPRpool(mPool.getVolatileAPRPool()) { }
~LLScopedVolatileAPRPool() { mPool.clearVolatileAPRPool(); }
// Only use this to pass the pointer to a libapr-1 function that requires it.
operator apr_pool_t*() const { return mScopedAPRpool; }
};
#endif

View File

@@ -72,8 +72,8 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
// Set thread state to running // Set thread state to running
threadp->mStatus = RUNNING; threadp->mStatus = RUNNING;
// Create a thread local APRFile pool. // Create a thread local data.
LLVolatileAPRPool::createLocalAPRFilePool(); AIThreadLocalData::create(threadp);
// Run the user supplied function // Run the user supplied function
threadp->run(); threadp->run();
@@ -87,24 +87,14 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
} }
LLThread::LLThread(const std::string& name, apr_pool_t *poolp) : LLThread::LLThread(std::string const& name) :
mPaused(FALSE), mPaused(FALSE),
mName(name), mName(name),
mAPRThreadp(NULL), mAPRThreadp(NULL),
mStatus(STOPPED) mStatus(STOPPED),
mThreadLocalData(NULL)
{ {
// Thread creation probably CAN be paranoid about APR being initialized, if necessary mRunCondition = new LLCondition;
if (poolp)
{
mIsLocalPool = FALSE;
mAPRPoolp = poolp;
}
else
{
mIsLocalPool = TRUE;
apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
}
mRunCondition = new LLCondition(mAPRPoolp);
} }
@@ -147,24 +137,18 @@ void LLThread::shutdown()
if (!isStopped()) if (!isStopped())
{ {
// This thread just wouldn't stop, even though we gave it time // This thread just wouldn't stop, even though we gave it time
llwarns << "LLThread::~LLThread() exiting thread before clean exit!" << llendl; llwarns << "LLThread::shutdown() exiting thread before clean exit!" << llendl;
return; return;
} }
mAPRThreadp = NULL; mAPRThreadp = NULL;
} }
delete mRunCondition; delete mRunCondition;
if (mIsLocalPool)
{
apr_pool_destroy(mAPRPoolp);
}
} }
void LLThread::start() void LLThread::start()
{ {
apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp); apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, tldata().mRootPool());
// We won't bother joining // We won't bother joining
apr_thread_detach(mAPRThreadp); apr_thread_detach(mAPRThreadp);
@@ -265,38 +249,72 @@ 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() { return apr_os_thread_equal(main_thread_id, apr_os_thread_current()); }
#endif
// The thread private handle to access the AIThreadLocalData instance.
apr_threadkey_t* AIThreadLocalData::sThreadLocalDataKey;
//static
void AIThreadLocalData::init(void)
{
// Only do this once.
if (sThreadLocalDataKey)
{
return;
}
apr_status_t status = apr_threadkey_private_create(&sThreadLocalDataKey, &AIThreadLocalData::destroy, AIAPRRootPool::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).
AIThreadLocalData::create(NULL);
#ifdef SHOW_ASSERT
// This function is called by the main thread.
main_thread_id = apr_os_thread_current();
#endif
}
// This is called once for every thread when the thread is destructed.
//static
void AIThreadLocalData::destroy(void* thread_local_data)
{
delete reinterpret_cast<AIThreadLocalData*>(thread_local_data);
}
//static
void AIThreadLocalData::create(LLThread* threadp)
{
AIThreadLocalData* new_tld = new AIThreadLocalData;
if (threadp)
{
threadp->mThreadLocalData = new_tld;
}
apr_status_t status = apr_threadkey_private_set(new_tld, sThreadLocalDataKey);
llassert_always(status == APR_SUCCESS);
}
//static
AIThreadLocalData& AIThreadLocalData::tldata(void)
{
if (!sThreadLocalDataKey)
AIThreadLocalData::init();
void* data;
apr_status_t status = apr_threadkey_private_get(&data, sThreadLocalDataKey);
llassert_always(status == APR_SUCCESS);
return *static_cast<AIThreadLocalData*>(data);
}
//============================================================================ //============================================================================
LLMutex::LLMutex(apr_pool_t *poolp) : bool LLMutexBase::isLocked()
mAPRMutexp(NULL)
{
//if (poolp)
//{
// mIsLocalPool = FALSE;
// mAPRPoolp = poolp;
//}
//else
{
mIsLocalPool = TRUE;
apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
}
apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp);
}
LLMutex::~LLMutex()
{
#if _DEBUG
llassert(!isLocked()); // better not be locked!
#endif
apr_thread_mutex_destroy(mAPRMutexp);
mAPRMutexp = NULL;
if (mIsLocalPool)
{
apr_pool_destroy(mAPRPoolp);
}
}
bool LLMutex::isLocked()
{ {
if (!tryLock()) if (!tryLock())
{ {
@@ -308,12 +326,9 @@ bool LLMutex::isLocked()
//============================================================================ //============================================================================
LLCondition::LLCondition(apr_pool_t *poolp) : LLCondition::LLCondition(AIAPRPool& parent) : LLMutex(parent)
LLMutex(poolp)
{ {
// base class (LLMutex) has already ensured that mAPRPoolp is set up. apr_thread_cond_create(&mAPRCondp, mPool());
apr_thread_cond_create(&mAPRCondp, mAPRPoolp);
} }
LLCondition::~LLCondition() LLCondition::~LLCondition()
@@ -349,7 +364,7 @@ void LLThreadSafeRefCount::initThreadSafeRefCount()
{ {
if (!sMutex) if (!sMutex)
{ {
sMutex = new LLMutex(0); sMutex = new LLMutex;
} }
} }

View File

@@ -38,11 +38,32 @@
#include "llmemory.h" #include "llmemory.h"
#include "apr_thread_cond.h" #include "apr_thread_cond.h"
#include "aiaprpool.h"
#ifdef SHOW_ASSERT
extern bool is_main_thread(void);
#endif
class LLThread; class LLThread;
class LLMutex; class LLMutex;
class LLCondition; class LLCondition;
class LL_COMMON_API AIThreadLocalData
{
private:
static apr_threadkey_t* sThreadLocalDataKey;
public:
// Thread-local memory pool.
AIAPRRootPool mRootPool;
AIVolatileAPRPool mVolatileAPRPool;
static void init(void);
static void destroy(void* thread_local_data);
static void create(LLThread* pthread);
static AIThreadLocalData& tldata(void);
};
class LL_COMMON_API LLThread class LL_COMMON_API LLThread
{ {
public: public:
@@ -53,7 +74,7 @@ public:
QUITTING= 2 // Someone wants this thread to quit QUITTING= 2 // Someone wants this thread to quit
} EThreadStatus; } EThreadStatus;
LLThread(const std::string& name, apr_pool_t *poolp = NULL); LLThread(std::string const& name);
virtual ~LLThread(); // Warning! You almost NEVER want to destroy a thread unless it's in the STOPPED state. virtual ~LLThread(); // Warning! You almost NEVER want to destroy a thread unless it's in the STOPPED state.
virtual void shutdown(); // stops the thread virtual void shutdown(); // stops the thread
@@ -82,7 +103,8 @@ public:
// this kicks off the apr thread // this kicks off the apr thread
void start(void); void start(void);
apr_pool_t *getAPRPool() { return mAPRPoolp; } // Return thread-local data for the current thread.
static AIThreadLocalData& tldata(void) { return AIThreadLocalData::tldata(); }
private: private:
BOOL mPaused; BOOL mPaused;
@@ -95,10 +117,11 @@ protected:
LLCondition* mRunCondition; LLCondition* mRunCondition;
apr_thread_t *mAPRThreadp; apr_thread_t *mAPRThreadp;
apr_pool_t *mAPRPoolp;
BOOL mIsLocalPool;
EThreadStatus mStatus; EThreadStatus mStatus;
friend void AIThreadLocalData::create(LLThread* threadp);
AIThreadLocalData* mThreadLocalData;
void setQuitting(); void setQuitting();
// virtual function overridden by subclass -- this will be called when the thread runs // virtual function overridden by subclass -- this will be called when the thread runs
@@ -125,12 +148,9 @@ protected:
//============================================================================ //============================================================================
class LL_COMMON_API LLMutex class LL_COMMON_API LLMutexBase
{ {
public: public:
LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex
~LLMutex();
void lock() { apr_thread_mutex_lock(mAPRMutexp); } void lock() { apr_thread_mutex_lock(mAPRMutexp); }
void unlock() { apr_thread_mutex_unlock(mAPRMutexp); } void unlock() { apr_thread_mutex_unlock(mAPRMutexp); }
// Returns true if lock was obtained successfully. // Returns true if lock was obtained successfully.
@@ -139,16 +159,60 @@ public:
bool isLocked(); // non-blocking, but does do a lock/unlock so not free bool isLocked(); // non-blocking, but does do a lock/unlock so not free
protected: protected:
apr_thread_mutex_t *mAPRMutexp; // mAPRMutexp is initialized and uninitialized in the derived class.
apr_pool_t *mAPRPoolp; apr_thread_mutex_t* mAPRMutexp;
BOOL mIsLocalPool;
}; };
class LL_COMMON_API LLMutex : public LLMutexBase
{
public:
LLMutex(AIAPRPool& parent = LLThread::tldata().mRootPool) : mPool(parent)
{
apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mPool());
}
~LLMutex()
{
llassert(!isLocked()); // better not be locked!
apr_thread_mutex_destroy(mAPRMutexp);
mAPRMutexp = NULL;
}
protected:
AIAPRPool 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, APR_THREAD_MUTEX_UNNESTED, mRootPool());
}
~LLMutexRootPool()
{
#if APR_POOL_DEBUG
// It is allowed to destruct root pools from a different thread.
mRootPool.grab_ownership();
#endif
llassert(!isLocked()); // better not be locked!
apr_thread_mutex_destroy(mAPRMutexp);
mAPRMutexp = NULL;
}
protected:
AIAPRRootPool mRootPool;
};
#endif // APR_HAS_THREADS
// Actually a condition/mutex pair (since each condition needs to be associated with a mutex). // Actually a condition/mutex pair (since each condition needs to be associated with a mutex).
class LL_COMMON_API LLCondition : public LLMutex class LL_COMMON_API LLCondition : public LLMutex
{ {
public: public:
LLCondition(apr_pool_t *apr_poolp); // Defaults to global pool, could use the thread pool as well. LLCondition(AIAPRPool& parent = LLThread::tldata().mRootPool);
~LLCondition(); ~LLCondition();
void wait(); // blocks void wait(); // blocks
@@ -162,7 +226,7 @@ protected:
class LL_COMMON_API LLMutexLock class LL_COMMON_API LLMutexLock
{ {
public: public:
LLMutexLock(LLMutex* mutex) LLMutexLock(LLMutexBase* mutex)
{ {
mMutex = mutex; mMutex = mutex;
mMutex->lock(); mMutex->lock();
@@ -172,7 +236,7 @@ public:
mMutex->unlock(); mMutex->unlock();
} }
private: private:
LLMutex* mMutex; LLMutexBase* mMutex;
}; };
//============================================================================ //============================================================================

View File

@@ -43,7 +43,7 @@
LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded) : LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded) :
LLQueuedThread(name, threaded) LLQueuedThread(name, threaded)
{ {
mDeleteMutex = new LLMutex(NULL); mDeleteMutex = new LLMutex;
} }
LLWorkerThread::~LLWorkerThread() LLWorkerThread::~LLWorkerThread()
@@ -205,7 +205,6 @@ LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& na
mRequestPriority(LLWorkerThread::PRIORITY_NORMAL), mRequestPriority(LLWorkerThread::PRIORITY_NORMAL),
mWorkerClassName(name), mWorkerClassName(name),
mRequestHandle(LLWorkerThread::nullHandle()), mRequestHandle(LLWorkerThread::nullHandle()),
mMutex(NULL),
mWorkFlags(0) mWorkFlags(0)
{ {
if (!mWorkerThread) if (!mWorkerThread)

View File

@@ -200,7 +200,7 @@ protected:
U32 mRequestPriority; // last priority set U32 mRequestPriority; // last priority set
private: private:
LLMutex mMutex; LLMutexRootPool mMutex; // Use LLMutexRootPool since this object is created and destructed by multiple threads.
LLAtomicU32 mWorkFlags; LLAtomicU32 mWorkFlags;
}; };

View File

@@ -387,8 +387,7 @@ bool LLCrashLogger::init()
return false; return false;
} }
gServicePump = new LLPumpIO(gAPRPoolp); gServicePump = new LLPumpIO;
gServicePump->prime(gAPRPoolp);
LLHTTPClient::setPump(*gServicePump); LLHTTPClient::setPump(*gServicePump);
//If we've opened the crash logger, assume we can delete the marker file if it exists //If we've opened the crash logger, assume we can delete the marker file if it exists

View File

@@ -57,7 +57,7 @@ LLMutex* LLImage::sMutex = NULL;
//static //static
void LLImage::initClass() void LLImage::initClass()
{ {
sMutex = new LLMutex(NULL); sMutex = new LLMutex;
LLImageJ2C::openDSO(); LLImageJ2C::openDSO();
} }

View File

@@ -46,7 +46,7 @@ typedef const char* (*EngineInfoLLImageJ2CFunction)();
CreateLLImageJ2CFunction j2cimpl_create_func; CreateLLImageJ2CFunction j2cimpl_create_func;
DestroyLLImageJ2CFunction j2cimpl_destroy_func; DestroyLLImageJ2CFunction j2cimpl_destroy_func;
EngineInfoLLImageJ2CFunction j2cimpl_engineinfo_func; EngineInfoLLImageJ2CFunction j2cimpl_engineinfo_func;
apr_pool_t *j2cimpl_dso_memory_pool; AIAPRPool j2cimpl_dso_memory_pool;
apr_dso_handle_t *j2cimpl_dso_handle; apr_dso_handle_t *j2cimpl_dso_handle;
//Declare the prototype for theses functions here, their functionality //Declare the prototype for theses functions here, their functionality
@@ -81,13 +81,12 @@ void LLImageJ2C::openDSO()
gDirUtilp->getExecutableDir()); gDirUtilp->getExecutableDir());
j2cimpl_dso_handle = NULL; j2cimpl_dso_handle = NULL;
j2cimpl_dso_memory_pool = NULL; j2cimpl_dso_memory_pool.create();
//attempt to load the shared library //attempt to load the shared library
apr_pool_create(&j2cimpl_dso_memory_pool, NULL);
rv = apr_dso_load(&j2cimpl_dso_handle, rv = apr_dso_load(&j2cimpl_dso_handle,
dso_path.c_str(), dso_path.c_str(),
j2cimpl_dso_memory_pool); j2cimpl_dso_memory_pool());
//now, check for success //now, check for success
if ( rv == APR_SUCCESS ) if ( rv == APR_SUCCESS )
@@ -151,11 +150,7 @@ void LLImageJ2C::openDSO()
j2cimpl_dso_handle = NULL; j2cimpl_dso_handle = NULL;
} }
if ( j2cimpl_dso_memory_pool ) j2cimpl_dso_memory_pool.destroy();
{
apr_pool_destroy(j2cimpl_dso_memory_pool);
j2cimpl_dso_memory_pool = NULL;
}
} }
} }
@@ -163,7 +158,7 @@ void LLImageJ2C::openDSO()
void LLImageJ2C::closeDSO() void LLImageJ2C::closeDSO()
{ {
if ( j2cimpl_dso_handle ) apr_dso_unload(j2cimpl_dso_handle); if ( j2cimpl_dso_handle ) apr_dso_unload(j2cimpl_dso_handle);
if (j2cimpl_dso_memory_pool) apr_pool_destroy(j2cimpl_dso_memory_pool); j2cimpl_dso_memory_pool.destroy();
} }
//static //static

View File

@@ -41,20 +41,13 @@
LLImageDecodeThread::LLImageDecodeThread(bool threaded) LLImageDecodeThread::LLImageDecodeThread(bool threaded)
: LLQueuedThread("imagedecode", threaded) : LLQueuedThread("imagedecode", threaded)
{ {
mCreationMutex = new LLMutex(getAPRPool());
}
//virtual
LLImageDecodeThread::~LLImageDecodeThread()
{
delete mCreationMutex ;
} }
// MAIN THREAD // MAIN THREAD
// virtual // virtual
S32 LLImageDecodeThread::update(U32 max_time_ms) S32 LLImageDecodeThread::update(U32 max_time_ms)
{ {
LLMutexLock lock(mCreationMutex); LLMutexLock lock(&mCreationMutex);
for (creation_list_t::iterator iter = mCreationList.begin(); for (creation_list_t::iterator iter = mCreationList.begin();
iter != mCreationList.end(); ++iter) iter != mCreationList.end(); ++iter)
{ {
@@ -77,7 +70,7 @@ S32 LLImageDecodeThread::update(U32 max_time_ms)
LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* image, LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* image,
U32 priority, S32 discard, BOOL needs_aux, Responder* responder) U32 priority, S32 discard, BOOL needs_aux, Responder* responder)
{ {
LLMutexLock lock(mCreationMutex); LLMutexLock lock(&mCreationMutex);
handle_t handle = generateHandle(); handle_t handle = generateHandle();
mCreationList.push_back(creation_info(handle, image, priority, discard, needs_aux, responder)); mCreationList.push_back(creation_info(handle, image, priority, discard, needs_aux, responder));
return handle; return handle;
@@ -87,7 +80,7 @@ LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted*
// Returns the size of the mutex guarded list as an indication of sanity // Returns the size of the mutex guarded list as an indication of sanity
S32 LLImageDecodeThread::tut_size() S32 LLImageDecodeThread::tut_size()
{ {
LLMutexLock lock(mCreationMutex); LLMutexLock lock(&mCreationMutex);
S32 res = mCreationList.size(); S32 res = mCreationList.size();
return res; return res;
} }

View File

@@ -78,8 +78,6 @@ public:
public: public:
LLImageDecodeThread(bool threaded = true); LLImageDecodeThread(bool threaded = true);
virtual ~LLImageDecodeThread();
handle_t decodeImage(LLImageFormatted* image, handle_t decodeImage(LLImageFormatted* image,
U32 priority, S32 discard, BOOL needs_aux, U32 priority, S32 discard, BOOL needs_aux,
Responder* responder); Responder* responder);
@@ -103,7 +101,7 @@ private:
}; };
typedef std::list<creation_info> creation_list_t; typedef std::list<creation_info> creation_list_t;
creation_list_t mCreationList; creation_list_t mCreationList;
LLMutex* mCreationMutex; LLMutex mCreationMutex;
}; };
#endif #endif

View File

@@ -55,7 +55,7 @@ LLVolumeMgr::LLVolumeMgr()
{ {
// the LLMutex magic interferes with easy unit testing, // the LLMutex magic interferes with easy unit testing,
// so you now must manually call useMutex() to use it // so you now must manually call useMutex() to use it
//mDataMutex = new LLMutex(gAPRPoolp); //mDataMutex = new LLMutex;
} }
LLVolumeMgr::~LLVolumeMgr() LLVolumeMgr::~LLVolumeMgr()
@@ -222,7 +222,7 @@ void LLVolumeMgr::useMutex()
{ {
if (!mDataMutex) if (!mDataMutex)
{ {
mDataMutex = new LLMutex(gAPRPoolp); mDataMutex = new LLMutex;
} }
} }

View File

@@ -44,6 +44,7 @@
#include "llapr.h" #include "llapr.h"
#define CARES_STATICLIB #define CARES_STATICLIB
#include "llares.h" #include "llares.h"
#include "llscopedvolatileaprpool.h"
#if defined(LL_WINDOWS) #if defined(LL_WINDOWS)
# define ns_c_in 1 # define ns_c_in 1
@@ -467,11 +468,6 @@ void LLAres::search(const std::string &query, LLResType type,
bool LLAres::process(U64 timeout) bool LLAres::process(U64 timeout)
{ {
if (!gAPRPoolp)
{
ll_init_apr();
}
ares_socket_t socks[ARES_GETSOCK_MAXNUM]; ares_socket_t socks[ARES_GETSOCK_MAXNUM];
apr_pollfd_t aprFds[ARES_GETSOCK_MAXNUM]; apr_pollfd_t aprFds[ARES_GETSOCK_MAXNUM];
apr_int32_t nsds = 0; apr_int32_t nsds = 0;
@@ -485,10 +481,7 @@ bool LLAres::process(U64 timeout)
return nsds > 0; return nsds > 0;
} }
apr_status_t status; LLScopedVolatileAPRPool scoped_pool;
LLAPRPool pool;
status = pool.getStatus() ;
ll_apr_assert_status(status);
for (int i = 0; i < ARES_GETSOCK_MAXNUM; i++) for (int i = 0; i < ARES_GETSOCK_MAXNUM; i++)
{ {
@@ -505,7 +498,7 @@ bool LLAres::process(U64 timeout)
apr_socket_t *aprSock = NULL; apr_socket_t *aprSock = NULL;
status = apr_os_sock_put(&aprSock, (apr_os_sock_t *) &socks[i], pool.getAPRPool()); apr_status_t status = apr_os_sock_put(&aprSock, (apr_os_sock_t *) &socks[i], scoped_pool);
if (status != APR_SUCCESS) if (status != APR_SUCCESS)
{ {
ll_apr_warn_status(status); ll_apr_warn_status(status);
@@ -514,7 +507,7 @@ bool LLAres::process(U64 timeout)
aprFds[nactive].desc.s = aprSock; aprFds[nactive].desc.s = aprSock;
aprFds[nactive].desc_type = APR_POLL_SOCKET; aprFds[nactive].desc_type = APR_POLL_SOCKET;
aprFds[nactive].p = pool.getAPRPool(); aprFds[nactive].p = scoped_pool;
aprFds[nactive].rtnevents = 0; aprFds[nactive].rtnevents = 0;
aprFds[nactive].client_data = &socks[i]; aprFds[nactive].client_data = &socks[i];
@@ -523,7 +516,7 @@ bool LLAres::process(U64 timeout)
if (nactive > 0) if (nactive > 0)
{ {
status = apr_poll(aprFds, nactive, &nsds, timeout); apr_status_t status = apr_poll(aprFds, nactive, &nsds, timeout);
if (status != APR_SUCCESS && status != APR_TIMEUP) if (status != APR_SUCCESS && status != APR_TIMEUP)
{ {

View File

@@ -1082,7 +1082,7 @@ void LLCurl::initClass()
S32 mutex_count = CRYPTO_num_locks(); S32 mutex_count = CRYPTO_num_locks();
for (S32 i=0; i<mutex_count; i++) for (S32 i=0; i<mutex_count; i++)
{ {
sSSLMutex.push_back(new LLMutex(NULL)); sSSLMutex.push_back(new LLMutex);
} }
CRYPTO_set_id_callback(&LLCurl::ssl_thread_id); CRYPTO_set_id_callback(&LLCurl::ssl_thread_id);
CRYPTO_set_locking_callback(&LLCurl::ssl_locking_callback); CRYPTO_set_locking_callback(&LLCurl::ssl_locking_callback);

View File

@@ -960,13 +960,9 @@ private:
// static // static
LLHTTPNode& LLIOHTTPServer::create( LLHTTPNode& LLIOHTTPServer::create(LLPumpIO& pump, U16 port)
apr_pool_t* pool, LLPumpIO& pump, U16 port)
{ {
LLSocket::ptr_t socket = LLSocket::create( LLSocket::ptr_t socket = LLSocket::create(LLSocket::STREAM_TCP, port);
pool,
LLSocket::STREAM_TCP,
port);
if(!socket) if(!socket)
{ {
llerrs << "Unable to initialize socket" << llendl; llerrs << "Unable to initialize socket" << llendl;
@@ -975,7 +971,7 @@ LLHTTPNode& LLIOHTTPServer::create(
LLHTTPResponseFactory* factory = new LLHTTPResponseFactory; LLHTTPResponseFactory* factory = new LLHTTPResponseFactory;
boost::shared_ptr<LLChainIOFactory> factory_ptr(factory); boost::shared_ptr<LLChainIOFactory> factory_ptr(factory);
LLIOServerSocket* server = new LLIOServerSocket(pool, socket, factory_ptr); LLIOServerSocket* server = new LLIOServerSocket(socket, factory_ptr);
LLPumpIO::chain_t chain; LLPumpIO::chain_t chain;
chain.push_back(LLIOPipe::ptr_t(server)); chain.push_back(LLIOPipe::ptr_t(server));

View File

@@ -56,7 +56,7 @@ class LLIOHTTPServer
public: public:
typedef void (*timing_callback_t)(const char* hashed_name, F32 time, void* data); typedef void (*timing_callback_t)(const char* hashed_name, F32 time, void* data);
static LLHTTPNode& create(apr_pool_t* pool, LLPumpIO& pump, U16 port); static LLHTTPNode& create(LLPumpIO& pump, U16 port);
/**< Creates an HTTP wire server on the pump for the given TCP 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 * Returns the root node of the new server. Add LLHTTPNode instances

View File

@@ -41,6 +41,7 @@
#include "llhost.h" #include "llhost.h"
#include "llmemtype.h" #include "llmemtype.h"
#include "llpumpio.h" #include "llpumpio.h"
#include "llthread.h"
// //
// constants // constants
@@ -104,51 +105,31 @@ void ll_debug_socket(const char* msg, apr_socket_t* apr_sock)
/// ///
// static // static
LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port) LLSocket::ptr_t LLSocket::create(EType type, U16 port)
{ {
LLMemType m1(LLMemType::MTYPE_IO_TCP); 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; 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) if(STREAM_TCP == type)
{ {
status = apr_socket_create( status = apr_socket_create(&rv->mSocket, APR_INET, SOCK_STREAM, APR_PROTO_TCP, rv->mPool());
&socket,
APR_INET,
SOCK_STREAM,
APR_PROTO_TCP,
new_pool);
} }
else if(DATAGRAM_UDP == type) else if(DATAGRAM_UDP == type)
{ {
status = apr_socket_create( status = apr_socket_create(&rv->mSocket, APR_INET, SOCK_DGRAM, APR_PROTO_UDP, rv->mPool());
&socket,
APR_INET,
SOCK_DGRAM,
APR_PROTO_UDP,
new_pool);
} }
else else
{ {
if(new_pool) apr_pool_destroy(new_pool); rv.reset();
return rv; return rv;
} }
if(ll_apr_warn_status(status)) if(ll_apr_warn_status(status))
{ {
if(new_pool) apr_pool_destroy(new_pool); rv->mSocket = NULL;
rv.reset();
return rv; return rv;
} }
rv = ptr_t(new LLSocket(socket, new_pool));
if(port > 0) if(port > 0)
{ {
apr_sockaddr_t* sa = NULL; apr_sockaddr_t* sa = NULL;
@@ -158,7 +139,7 @@ LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port)
APR_UNSPEC, APR_UNSPEC,
port, port,
0, 0,
new_pool); rv->mPool());
if(ll_apr_warn_status(status)) if(ll_apr_warn_status(status))
{ {
rv.reset(); rv.reset();
@@ -166,8 +147,8 @@ LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port)
} }
// This allows us to reuse the address on quick down/up. This // This allows us to reuse the address on quick down/up. This
// is unlikely to create problems. // is unlikely to create problems.
ll_apr_warn_status(apr_socket_opt_set(socket, APR_SO_REUSEADDR, 1)); ll_apr_warn_status(apr_socket_opt_set(rv->mSocket, APR_SO_REUSEADDR, 1));
status = apr_socket_bind(socket, sa); status = apr_socket_bind(rv->mSocket, sa);
if(ll_apr_warn_status(status)) if(ll_apr_warn_status(status))
{ {
rv.reset(); rv.reset();
@@ -181,7 +162,7 @@ LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port)
// to keep a queue of incoming connections for ACCEPT. // to keep a queue of incoming connections for ACCEPT.
lldebugs << "Setting listen state for socket." << llendl; lldebugs << "Setting listen state for socket." << llendl;
status = apr_socket_listen( status = apr_socket_listen(
socket, rv->mSocket,
LL_DEFAULT_LISTEN_BACKLOG); LL_DEFAULT_LISTEN_BACKLOG);
if(ll_apr_warn_status(status)) if(ll_apr_warn_status(status))
{ {
@@ -202,21 +183,28 @@ LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port)
} }
// static // static
LLSocket::ptr_t LLSocket::create(apr_socket_t* socket, apr_pool_t* pool) LLSocket::ptr_t LLSocket::create(apr_status_t& status, LLSocket::ptr_t& listen_socket)
{ {
LLMemType m1(LLMemType::MTYPE_IO_TCP); LLMemType m1(LLMemType::MTYPE_IO_TCP);
LLSocket::ptr_t rv; if (!listen_socket->getSocket())
if(!socket)
{ {
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)
{
rv->mSocket = NULL;
rv.reset();
return rv; return rv;
} }
rv = ptr_t(new LLSocket(socket, pool));
rv->mPort = PORT_EPHEMERAL; rv->mPort = PORT_EPHEMERAL;
rv->setOptions(); rv->setOptions();
return rv; return rv;
} }
bool LLSocket::blockingConnect(const LLHost& host) bool LLSocket::blockingConnect(const LLHost& host)
{ {
if(!mSocket) return false; if(!mSocket) return false;
@@ -229,7 +217,7 @@ bool LLSocket::blockingConnect(const LLHost& host)
APR_UNSPEC, APR_UNSPEC,
host.getPort(), host.getPort(),
0, 0,
mPool))) mPool())))
{ {
return false; return false;
} }
@@ -240,13 +228,11 @@ bool LLSocket::blockingConnect(const LLHost& host)
return true; return true;
} }
LLSocket::LLSocket(apr_socket_t* socket, apr_pool_t* pool) : LLSocket::LLSocket() :
mSocket(socket), mSocket(NULL),
mPool(pool), mPool(LLThread::tldata().mRootPool),
mPort(PORT_INVALID) mPort(PORT_INVALID)
{ {
ll_debug_socket("Constructing wholely formed socket", mSocket);
LLMemType m1(LLMemType::MTYPE_IO_TCP);
} }
LLSocket::~LLSocket() LLSocket::~LLSocket()
@@ -258,10 +244,6 @@ LLSocket::~LLSocket()
ll_debug_socket("Destroying socket", mSocket); ll_debug_socket("Destroying socket", mSocket);
apr_socket_close(mSocket); apr_socket_close(mSocket);
} }
if(mPool)
{
apr_pool_destroy(mPool);
}
} }
void LLSocket::setOptions() void LLSocket::setOptions()
@@ -522,10 +504,8 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl(
/// ///
LLIOServerSocket::LLIOServerSocket( LLIOServerSocket::LLIOServerSocket(
apr_pool_t* pool,
LLIOServerSocket::socket_t listener, LLIOServerSocket::socket_t listener,
factory_t factory) : factory_t factory) :
mPool(pool),
mListenSocket(listener), mListenSocket(listener),
mReactor(factory), mReactor(factory),
mInitialized(false), mInitialized(false),
@@ -585,21 +565,15 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
lldebugs << "accepting socket" << llendl; lldebugs << "accepting socket" << llendl;
PUMP_DEBUG; PUMP_DEBUG;
apr_pool_t* new_pool = NULL; apr_status_t status;
apr_status_t status = apr_pool_create(&new_pool, mPool); LLSocket::ptr_t llsocket(LLSocket::create(status, mListenSocket));
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; //EStatus rv = STATUS_ERROR;
if(llsocket) if(llsocket && status == APR_SUCCESS)
{ {
PUMP_DEBUG; PUMP_DEBUG;
apr_sockaddr_t* remote_addr; apr_sockaddr_t* remote_addr;
apr_socket_addr_get(&remote_addr, APR_REMOTE, socket); apr_socket_addr_get(&remote_addr, APR_REMOTE, llsocket->getSocket());
char* remote_host_string; char* remote_host_string;
apr_sockaddr_ip_get(&remote_host_string, remote_addr); apr_sockaddr_ip_get(&remote_host_string, remote_addr);
@@ -614,7 +588,6 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
{ {
chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(llsocket))); chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(llsocket)));
pump->addChain(chain, mResponseTimeout); pump->addChain(chain, mResponseTimeout);
status = STATUS_OK;
} }
else else
{ {
@@ -623,7 +596,8 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
} }
else else
{ {
llwarns << "Unable to create linden socket." << llendl; char buf[256];
llwarns << "Unable to accept linden socket: " << apr_strerror(status, buf, sizeof(buf)) << llendl;
} }
PUMP_DEBUG; PUMP_DEBUG;
@@ -636,11 +610,10 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
#if 0 #if 0
LLIODataSocket::LLIODataSocket( LLIODataSocket::LLIODataSocket(
U16 suggested_port, U16 suggested_port,
U16 start_discovery_port, U16 start_discovery_port) :
apr_pool_t* pool) :
mSocket(NULL) mSocket(NULL)
{ {
if(!pool || (PORT_INVALID == suggested_port)) return; if(PORT_INVALID == suggested_port) return;
if(ll_apr_warn_status(apr_socket_create(&mSocket, APR_INET, SOCK_DGRAM, APR_PROTO_UDP, pool))) return; if(ll_apr_warn_status(apr_socket_create(&mSocket, APR_INET, SOCK_DGRAM, APR_PROTO_UDP, pool))) return;
apr_sockaddr_t* sa = NULL; apr_sockaddr_t* sa = NULL;
if(ll_apr_warn_status(apr_sockaddr_info_get(&sa, APR_ANYADDR, APR_UNSPEC, suggested_port, 0, pool))) return; if(ll_apr_warn_status(apr_sockaddr_info_get(&sa, APR_ANYADDR, APR_UNSPEC, suggested_port, 0, pool))) return;

View File

@@ -44,7 +44,6 @@
*/ */
#include "lliopipe.h" #include "lliopipe.h"
#include "apr_pools.h"
#include "apr_network_io.h" #include "apr_network_io.h"
#include "llchainio.h" #include "llchainio.h"
@@ -94,34 +93,22 @@ public:
* socket. If you intend the socket to be known to external * socket. If you intend the socket to be known to external
* clients without prior port notification, do not use * clients without prior port notification, do not use
* PORT_EPHEMERAL. * 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 type The type of socket to create
* @param port The port for the socket * @param port The port for the socket
* @return A valid socket shared pointer if the call worked. * @return A valid socket shared pointer if the call worked.
*/ */
static ptr_t create( static ptr_t create(
apr_pool_t* pool,
EType type, EType type,
U16 port = PORT_EPHEMERAL); U16 port = PORT_EPHEMERAL);
/** /**
* @brief Create a LLSocket when you already have an apr socket. * @brief Create a LLSocket by accepting a connection from a listen socket.
* *
* This method assumes an ephemeral port. This is typically used * @param status Output. Status of the accept if a valid listen socket was passed.
* by calls which spawn a socket such as a call to * @param listen_socket The listen socket to use.
* <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. * @return A valid socket shared pointer if the call worked.
*/ */
static ptr_t create(apr_socket_t* socket, apr_pool_t* pool); static ptr_t create(apr_status_t& status, ptr_t& listen_socket);
/** /**
* @brief Perform a blocking connect to a host. Do not use in production. * @brief Perform a blocking connect to a host. Do not use in production.
@@ -156,7 +143,7 @@ protected:
* @brief Protected constructor since should only make sockets * @brief Protected constructor since should only make sockets
* with one of the two <code>create()</code> calls. * with one of the two <code>create()</code> calls.
*/ */
LLSocket(apr_socket_t* socket, apr_pool_t* pool); LLSocket(void);
/** /**
* @brief Set default socket options. * @brief Set default socket options.
@@ -173,8 +160,8 @@ protected:
// The apr socket. // The apr socket.
apr_socket_t* mSocket; apr_socket_t* mSocket;
// our memory pool // Our memory pool.
apr_pool_t* mPool; AIAPRPool mPool;
// The port if we know it. // The port if we know it.
U16 mPort; U16 mPort;
@@ -299,7 +286,7 @@ class LLIOServerSocket : public LLIOPipe
public: public:
typedef LLSocket::ptr_t socket_t; typedef LLSocket::ptr_t socket_t;
typedef boost::shared_ptr<LLChainIOFactory> factory_t; typedef boost::shared_ptr<LLChainIOFactory> factory_t;
LLIOServerSocket(apr_pool_t* pool, socket_t listener, factory_t reactor); LLIOServerSocket(socket_t listener, factory_t reactor);
virtual ~LLIOServerSocket(); virtual ~LLIOServerSocket();
/** /**
@@ -331,7 +318,6 @@ protected:
//@} //@}
protected: protected:
apr_pool_t* mPool;
socket_t mListenSocket; socket_t mListenSocket;
factory_t mReactor; factory_t mReactor;
bool mInitialized; bool mInitialized;
@@ -365,8 +351,7 @@ public:
*/ */
LLIODataSocket( LLIODataSocket(
U16 suggested_port, U16 suggested_port,
U16 start_discovery_port, U16 start_discovery_port);
apr_pool_t* pool);
virtual ~LLIODataSocket(); virtual ~LLIODataSocket();
protected: protected:

View File

@@ -56,6 +56,7 @@
#include "llstring.h" #include "llstring.h"
#include "lluuid.h" #include "lluuid.h"
#include "net.h" #include "net.h"
#include "aiaprpool.h"
// //
// constants // constants
@@ -63,7 +64,7 @@
const size_t LL_MAX_KNOWN_GOOD_MAIL_SIZE = 4096; const size_t LL_MAX_KNOWN_GOOD_MAIL_SIZE = 4096;
static bool gMailEnabled = true; static bool gMailEnabled = true;
static apr_pool_t* gMailPool; static AIAPRPool gMailPool;
static apr_sockaddr_t* gSockAddr; static apr_sockaddr_t* gSockAddr;
static apr_socket_t* gMailSocket; static apr_socket_t* gMailSocket;
@@ -88,7 +89,7 @@ bool connect_smtp()
gSockAddr->sa.sin.sin_family, gSockAddr->sa.sin.sin_family,
SOCK_STREAM, SOCK_STREAM,
APR_PROTO_TCP, APR_PROTO_TCP,
gMailPool); gMailPool());
if(ll_apr_warn_status(status)) return false; if(ll_apr_warn_status(status)) return false;
status = apr_socket_connect(gMailSocket, gSockAddr); status = apr_socket_connect(gMailSocket, gSockAddr);
if(ll_apr_warn_status(status)) if(ll_apr_warn_status(status))
@@ -145,19 +146,19 @@ BOOL LLMail::send(
} }
// static // static
void LLMail::init(const std::string& hostname, apr_pool_t* pool) void LLMail::init(const std::string& hostname)
{ {
gMailSocket = NULL; gMailSocket = NULL;
if(hostname.empty() || !pool) if (hostname.empty())
{ {
gMailPool = NULL;
gSockAddr = NULL; gSockAddr = NULL;
gMailPool.destroy();
} }
else else
{ {
gMailPool = pool; gMailPool.create();
// collect all the information into a socaddr sturcture. the // Collect all the information into a sockaddr structure. the
// documentation is a bit unclear, but I either have to // documentation is a bit unclear, but I either have to
// specify APR_UNSPEC or not specify any flags. I am not sure // specify APR_UNSPEC or not specify any flags. I am not sure
// which option is better. // which option is better.
@@ -167,7 +168,7 @@ void LLMail::init(const std::string& hostname, apr_pool_t* pool)
APR_UNSPEC, APR_UNSPEC,
25, 25,
APR_IPV4_ADDR_OK, APR_IPV4_ADDR_OK,
gMailPool); gMailPool());
ll_apr_warn_status(status); ll_apr_warn_status(status);
} }
} }

View File

@@ -33,15 +33,13 @@
#ifndef LL_LLMAIL_H #ifndef LL_LLMAIL_H
#define LL_LLMAIL_H #define LL_LLMAIL_H
typedef struct apr_pool_t apr_pool_t;
#include "llsd.h" #include "llsd.h"
class LLMail class LLMail
{ {
public: public:
// if hostname is NULL, then the host is resolved as 'mail' // if hostname is NULL, then the host is resolved as 'mail'
static void init(const std::string& hostname, apr_pool_t* pool); static void init(const std::string& hostname);
// Allow all email transmission to be disabled/enabled. // Allow all email transmission to be disabled/enabled.
static void enable(bool mail_enabled); static void enable(bool mail_enabled);

View File

@@ -43,6 +43,7 @@
#include "llmemtype.h" #include "llmemtype.h"
#include "llstl.h" #include "llstl.h"
#include "llstat.h" #include "llstat.h"
#include "llthread.h"
#include "llfasttimer.h" #include "llfasttimer.h"
#include <iterator> //VS2010 #include <iterator> //VS2010
@@ -170,14 +171,12 @@ struct ll_delete_apr_pollset_fd_client_data
/** /**
* LLPumpIO * LLPumpIO
*/ */
LLPumpIO::LLPumpIO(apr_pool_t* pool) : LLPumpIO::LLPumpIO(void) :
mState(LLPumpIO::NORMAL), mState(LLPumpIO::NORMAL),
mRebuildPollset(false), mRebuildPollset(false),
mPollset(NULL), mPollset(NULL),
mPollsetClientID(0), mPollsetClientID(0),
mNextLock(0), mNextLock(0),
mPool(NULL),
mCurrentPool(NULL),
mCurrentPoolReallocCount(0), mCurrentPoolReallocCount(0),
mChainsMutex(NULL), mChainsMutex(NULL),
mCallbackMutex(NULL), mCallbackMutex(NULL),
@@ -186,21 +185,24 @@ LLPumpIO::LLPumpIO(apr_pool_t* pool) :
mCurrentChain = mRunningChains.end(); mCurrentChain = mRunningChains.end();
LLMemType m1(LLMemType::MTYPE_IO_PUMP); LLMemType m1(LLMemType::MTYPE_IO_PUMP);
initialize(pool); initialize();
} }
LLPumpIO::~LLPumpIO() LLPumpIO::~LLPumpIO()
{ {
LLMemType m1(LLMemType::MTYPE_IO_PUMP); LLMemType m1(LLMemType::MTYPE_IO_PUMP);
cleanup(); #if LL_THREADS_APR
} if (mChainsMutex) apr_thread_mutex_destroy(mChainsMutex);
if (mCallbackMutex) apr_thread_mutex_destroy(mCallbackMutex);
bool LLPumpIO::prime(apr_pool_t* pool) #endif
{ mChainsMutex = NULL;
LLMemType m1(LLMemType::MTYPE_IO_PUMP); mCallbackMutex = NULL;
cleanup(); if(mPollset)
initialize(pool); {
return ((pool == NULL) ? false : true); // lldebugs << "cleaning up pollset" << llendl;
apr_pollset_destroy(mPollset);
mPollset = NULL;
}
} }
bool LLPumpIO::addChain(const chain_t& chain, F32 timeout) bool LLPumpIO::addChain(const chain_t& chain, F32 timeout)
@@ -360,8 +362,7 @@ bool LLPumpIO::setConditional(LLIOPipe* pipe, const apr_pollfd_t* poll)
{ {
// each fd needs a pool to work with, so if one was // each fd needs a pool to work with, so if one was
// not specified, use this pool. // not specified, use this pool.
// *FIX: Should it always be this pool? value.second.p = (*mCurrentChain).mDescriptorsPool->operator()();
value.second.p = mPool;
} }
value.second.client_data = new S32(++mPollsetClientID); value.second.client_data = new S32(++mPollsetClientID);
(*mCurrentChain).mDescriptors.push_back(value); (*mCurrentChain).mDescriptors.push_back(value);
@@ -828,39 +829,15 @@ void LLPumpIO::control(LLPumpIO::EControl op)
} }
} }
void LLPumpIO::initialize(apr_pool_t* pool) void LLPumpIO::initialize(void)
{ {
LLMemType m1(LLMemType::MTYPE_IO_PUMP); LLMemType m1(LLMemType::MTYPE_IO_PUMP);
if(!pool) return; mPool.create();
#if LL_THREADS_APR #if LL_THREADS_APR
// SJB: Windows defaults to NESTED and OSX defaults to UNNESTED, so use UNNESTED explicitly. // SJB: Windows defaults to NESTED and OSX defaults to UNNESTED, so use UNNESTED explicitly.
apr_thread_mutex_create(&mChainsMutex, APR_THREAD_MUTEX_UNNESTED, pool); apr_thread_mutex_create(&mChainsMutex, APR_THREAD_MUTEX_UNNESTED, mPool());
apr_thread_mutex_create(&mCallbackMutex, APR_THREAD_MUTEX_UNNESTED, pool); apr_thread_mutex_create(&mCallbackMutex, APR_THREAD_MUTEX_UNNESTED, mPool());
#endif #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() void LLPumpIO::rebuildPollset()
@@ -888,21 +865,19 @@ void LLPumpIO::rebuildPollset()
if(mCurrentPool if(mCurrentPool
&& (0 == (++mCurrentPoolReallocCount % POLLSET_POOL_RECYCLE_COUNT))) && (0 == (++mCurrentPoolReallocCount % POLLSET_POOL_RECYCLE_COUNT)))
{ {
apr_pool_destroy(mCurrentPool); mCurrentPool.destroy();
mCurrentPool = NULL;
mCurrentPoolReallocCount = 0; mCurrentPoolReallocCount = 0;
} }
if(!mCurrentPool) if(!mCurrentPool)
{ {
apr_status_t status = apr_pool_create(&mCurrentPool, mPool); mCurrentPool.create(mPool);
(void)ll_apr_warn_status(status);
} }
// add all of the file descriptors // add all of the file descriptors
run_it = mRunningChains.begin(); run_it = mRunningChains.begin();
LLChainInfo::conditionals_t::iterator fd_it; LLChainInfo::conditionals_t::iterator fd_it;
LLChainInfo::conditionals_t::iterator fd_end; 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) for(; run_it != run_end; ++run_it)
{ {
fd_it = (*run_it).mDescriptors.begin(); fd_it = (*run_it).mDescriptors.begin();
@@ -1160,7 +1135,8 @@ bool LLPumpIO::handleChainError(
LLPumpIO::LLChainInfo::LLChainInfo() : LLPumpIO::LLChainInfo::LLChainInfo() :
mInit(false), mInit(false),
mLock(0), mLock(0),
mEOS(false) mEOS(false),
mDescriptorsPool(new AIAPRPool(LLThread::tldata().mRootPool))
{ {
LLMemType m1(LLMemType::MTYPE_IO_PUMP); LLMemType m1(LLMemType::MTYPE_IO_PUMP);
mTimer.setTimerExpirySec(DEFAULT_CHAIN_EXPIRY_SECS); mTimer.setTimerExpirySec(DEFAULT_CHAIN_EXPIRY_SECS);

View File

@@ -36,11 +36,12 @@
#define LL_LLPUMPIO_H #define LL_LLPUMPIO_H
#include <set> #include <set>
#include <boost/shared_ptr.hpp>
#if LL_LINUX // needed for PATH_MAX in APR. #if LL_LINUX // needed for PATH_MAX in APR.
#include <sys/param.h> #include <sys/param.h>
#endif #endif
#include "apr_pools.h" #include "aiaprpool.h"
#include "llbuffer.h" #include "llbuffer.h"
#include "llframetimer.h" #include "llframetimer.h"
#include "lliopipe.h" #include "lliopipe.h"
@@ -64,9 +65,8 @@ extern const F32 NEVER_CHAIN_EXPIRY_SECS;
* <code>pump()</code> on a thread used for IO and call * <code>pump()</code> on a thread used for IO and call
* <code>respond()</code> on a thread that is expected to do higher * <code>respond()</code> on a thread that is expected to do higher
* level processing. You can call almost any other method from any * level processing. You can call almost any other method from any
* thread - see notes for each method for details. In order for the * thread - see notes for each method for details.
* 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 * 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 * 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 * chain, the buffer, and if any pipe has marked the stream or process
@@ -85,24 +85,13 @@ public:
/** /**
* @brief Constructor. * @brief Constructor.
*/ */
LLPumpIO(apr_pool_t* pool); LLPumpIO(void);
/** /**
* @brief Destructor. * @brief Destructor.
*/ */
~LLPumpIO(); ~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. * @brief Typedef for having a chain of pipes.
*/ */
@@ -374,6 +363,7 @@ protected:
typedef std::pair<LLIOPipe::ptr_t, apr_pollfd_t> pipe_conditional_t; typedef std::pair<LLIOPipe::ptr_t, apr_pollfd_t> pipe_conditional_t;
typedef std::vector<pipe_conditional_t> conditionals_t; typedef std::vector<pipe_conditional_t> conditionals_t;
conditionals_t mDescriptors; conditionals_t mDescriptors;
boost::shared_ptr<AIAPRPool> mDescriptorsPool;
}; };
// All the running chains & info // All the running chains & info
@@ -392,9 +382,9 @@ protected:
callbacks_t mPendingCallbacks; callbacks_t mPendingCallbacks;
callbacks_t mCallbacks; callbacks_t mCallbacks;
// memory allocator for pollsets & mutexes. // Memory pool for pollsets & mutexes.
apr_pool_t* mPool; AIAPRPool mPool;
apr_pool_t* mCurrentPool; AIAPRPool mCurrentPool;
S32 mCurrentPoolReallocCount; S32 mCurrentPoolReallocCount;
#if LL_THREADS_APR #if LL_THREADS_APR
@@ -406,8 +396,7 @@ protected:
#endif #endif
protected: protected:
void initialize(apr_pool_t* pool); void initialize();
void cleanup();
/** /**
* @brief Given the internal state of the chains, rebuild the pollset * @brief Given the internal state of the chains, rebuild the pollset

View File

@@ -45,6 +45,7 @@
#include "llstring.h" #include "llstring.h"
#include "apr_env.h" #include "apr_env.h"
#include "llapr.h" #include "llapr.h"
#include "llscopedvolatileaprpool.h"
static const U32 HTTP_STATUS_PIPE_ERROR = 499; static const U32 HTTP_STATUS_PIPE_ERROR = 499;
/** /**
@@ -161,27 +162,31 @@ void LLURLRequest::setCallback(LLURLRequestComplete* callback)
// is called with use_proxy = FALSE // is called with use_proxy = FALSE
void LLURLRequest::useProxy(bool use_proxy) void LLURLRequest::useProxy(bool use_proxy)
{ {
static char *env_proxy; static std::string env_proxy;
if (use_proxy && (env_proxy == NULL)) if (use_proxy && env_proxy.empty())
{ {
apr_status_t status; char* env_proxy_str;
LLAPRPool pool; LLScopedVolatileAPRPool scoped_pool;
status = apr_env_get(&env_proxy, "ALL_PROXY", pool.getAPRPool()); apr_status_t status = apr_env_get(&env_proxy_str, "ALL_PROXY", scoped_pool);
if (status != APR_SUCCESS) if (status != APR_SUCCESS)
{ {
status = apr_env_get(&env_proxy, "http_proxy", pool.getAPRPool()); status = apr_env_get(&env_proxy_str, "http_proxy", scoped_pool);
} }
if (status != APR_SUCCESS) if (status != APR_SUCCESS)
{ {
use_proxy = FALSE; use_proxy = false;
} }
else
{
// env_proxy_str is stored in the scoped_pool, so we have to make a copy.
env_proxy = env_proxy_str;
}
} }
lldebugs << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = \"" << env_proxy << "\"" << llendl;
lldebugs << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (env_proxy ? env_proxy : "(null)") << llendl; if (use_proxy)
if (env_proxy && use_proxy)
{ {
mDetail->mCurlRequest->setoptString(CURLOPT_PROXY, env_proxy); mDetail->mCurlRequest->setoptString(CURLOPT_PROXY, env_proxy);
} }

View File

@@ -107,8 +107,10 @@ std::string get_shared_secret();
class LLMessagePollInfo class LLMessagePollInfo
{ {
public: public:
LLMessagePollInfo(void) : mPool(LLThread::tldata().mRootPool) { }
apr_socket_t *mAPRSocketp; apr_socket_t *mAPRSocketp;
apr_pollfd_t mPollFD; apr_pollfd_t mPollFD;
AIAPRPool mPool;
}; };
namespace namespace
@@ -297,20 +299,13 @@ LLMessageSystem::LLMessageSystem(const std::string& filename, U32 port,
} }
// LL_DEBUGS("Messaging") << << "*** port: " << mPort << llendl; // LL_DEBUGS("Messaging") << << "*** port: " << mPort << llendl;
//
// 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, gAPRPoolp);
mPollInfop = new LLMessagePollInfo; mPollInfop = new LLMessagePollInfo;
apr_socket_t *aprSocketp = NULL;
apr_os_sock_put(&aprSocketp, (apr_os_sock_t*)&mSocket, mPollInfop->mPool());
mPollInfop->mAPRSocketp = aprSocketp; mPollInfop->mAPRSocketp = aprSocketp;
mPollInfop->mPollFD.p = gAPRPoolp; mPollInfop->mPollFD.p = mPollInfop->mPool();
mPollInfop->mPollFD.desc_type = APR_POLL_SOCKET; mPollInfop->mPollFD.desc_type = APR_POLL_SOCKET;
mPollInfop->mPollFD.reqevents = APR_POLLIN; mPollInfop->mPollFD.reqevents = APR_POLLIN;
mPollInfop->mPollFD.rtnevents = 0; mPollInfop->mPollFD.rtnevents = 0;

View File

@@ -36,8 +36,7 @@
#include "linden_common.h" #include "linden_common.h"
#include "llplugininstance.h" #include "llplugininstance.h"
#include "aiaprpool.h"
#include "llapr.h"
/** Virtual destructor. */ /** Virtual destructor. */
LLPluginInstanceMessageListener::~LLPluginInstanceMessageListener() LLPluginInstanceMessageListener::~LLPluginInstanceMessageListener()
@@ -86,7 +85,7 @@ int LLPluginInstance::load(std::string &plugin_file)
int result = apr_dso_load(&mDSOHandle, int result = apr_dso_load(&mDSOHandle,
plugin_file.c_str(), plugin_file.c_str(),
gAPRPoolp); AIAPRRootPool::get()());
if(result != APR_SUCCESS) if(result != APR_SUCCESS)
{ {
char buf[1024]; char buf[1024];

View File

@@ -99,8 +99,6 @@ void LLPluginMessagePipeOwner::killMessagePipe(void)
} }
LLPluginMessagePipe::LLPluginMessagePipe(LLPluginMessagePipeOwner *owner, LLSocket::ptr_t socket): LLPluginMessagePipe::LLPluginMessagePipe(LLPluginMessagePipeOwner *owner, LLSocket::ptr_t socket):
mInputMutex(gAPRPoolp),
mOutputMutex(gAPRPoolp),
mOwner(owner), mOwner(owner),
mSocket(socket) mSocket(socket)
{ {

View File

@@ -47,7 +47,7 @@ LLPluginProcessChild::LLPluginProcessChild()
{ {
mState = STATE_UNINITIALIZED; mState = STATE_UNINITIALIZED;
mInstance = NULL; mInstance = NULL;
mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); mSocket = LLSocket::create(LLSocket::STREAM_TCP);
mSleepTime = PLUGIN_IDLE_SECONDS; // default: send idle messages at 100Hz mSleepTime = PLUGIN_IDLE_SECONDS; // default: send idle messages at 100Hz
mCPUElapsed = 0.0f; mCPUElapsed = 0.0f;
mBlockingRequest = false; mBlockingRequest = false;

View File

@@ -49,6 +49,7 @@ LLPluginProcessParentOwner::~LLPluginProcessParentOwner()
bool LLPluginProcessParent::sUseReadThread = false; bool LLPluginProcessParent::sUseReadThread = false;
apr_pollset_t *LLPluginProcessParent::sPollSet = NULL; apr_pollset_t *LLPluginProcessParent::sPollSet = NULL;
AIAPRPool LLPluginProcessParent::sPollSetPool;
bool LLPluginProcessParent::sPollsetNeedsRebuild = false; bool LLPluginProcessParent::sPollsetNeedsRebuild = false;
LLMutex *LLPluginProcessParent::sInstancesMutex; LLMutex *LLPluginProcessParent::sInstancesMutex;
std::list<LLPluginProcessParent*> LLPluginProcessParent::sInstances; std::list<LLPluginProcessParent*> LLPluginProcessParent::sInstances;
@@ -59,7 +60,7 @@ class LLPluginProcessParentPollThread: public LLThread
{ {
public: public:
LLPluginProcessParentPollThread() : LLPluginProcessParentPollThread() :
LLThread("LLPluginProcessParentPollThread", gAPRPoolp) LLThread("LLPluginProcessParentPollThread")
{ {
} }
protected: protected:
@@ -84,12 +85,11 @@ protected:
}; };
LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner): LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner)
mIncomingQueueMutex(gAPRPoolp)
{ {
if(!sInstancesMutex) if(!sInstancesMutex)
{ {
sInstancesMutex = new LLMutex(gAPRPoolp); sInstancesMutex = new LLMutex;
} }
mOwner = owner; mOwner = owner;
@@ -102,6 +102,7 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner):
mBlocked = false; mBlocked = false;
mPolledInput = false; mPolledInput = false;
mPollFD.client_data = NULL; mPollFD.client_data = NULL;
mPollFDPool.create();
mPluginLaunchTimeout = 60.0f; mPluginLaunchTimeout = 60.0f;
mPluginLockupTimeout = 15.0f; mPluginLockupTimeout = 15.0f;
@@ -177,44 +178,28 @@ void LLPluginProcessParent::init(const std::string &launcher_filename, const std
bool LLPluginProcessParent::accept() bool LLPluginProcessParent::accept()
{ {
bool result = false; bool result = false;
apr_status_t status = APR_EGENERAL; 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) if(status == APR_SUCCESS)
{ {
// llinfos << "SUCCESS" << llendl; // llinfos << "SUCCESS" << llendl;
// Success. Create a message pipe on the new socket // 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); new LLPluginMessagePipe(this, mSocket);
result = true; result = true;
} }
else if(APR_STATUS_IS_EAGAIN(status))
{
// llinfos << "EAGAIN" << llendl;
// No incoming connections. This is not an error.
status = APR_SUCCESS;
}
else else
{ {
// llinfos << "Error:" << llendl; mSocket.reset();
ll_apr_warn_status(status); // EAGAIN means "No incoming connections". This is not an error.
if (!APR_STATUS_IS_EAGAIN(status))
// Some other error. {
errorState(); // Some other error.
ll_apr_warn_status(status);
errorState();
}
} }
return result; return result;
@@ -283,7 +268,7 @@ void LLPluginProcessParent::idle(void)
apr_status_t status = APR_SUCCESS; apr_status_t status = APR_SUCCESS;
apr_sockaddr_t* addr = NULL; apr_sockaddr_t* addr = NULL;
mListenSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); mListenSocket = LLSocket::create(LLSocket::STREAM_TCP);
mBoundPort = 0; mBoundPort = 0;
// This code is based on parts of LLSocket::create() in lliosocket.cpp. // This code is based on parts of LLSocket::create() in lliosocket.cpp.
@@ -294,7 +279,7 @@ void LLPluginProcessParent::idle(void)
APR_INET, APR_INET,
0, // port 0 = ephemeral ("find me a port") 0, // port 0 = ephemeral ("find me a port")
0, 0,
gAPRPoolp); AIAPRRootPool::get()());
if(ll_apr_warn_status(status)) if(ll_apr_warn_status(status))
{ {
@@ -617,7 +602,8 @@ void LLPluginProcessParent::setMessagePipe(LLPluginMessagePipe *message_pipe)
if(message_pipe != NULL) if(message_pipe != NULL)
{ {
// Set up the apr_pollfd_t // Set up the apr_pollfd_t
mPollFD.p = gAPRPoolp;
mPollFD.p = mPollFDPool();
mPollFD.desc_type = APR_POLL_SOCKET; mPollFD.desc_type = APR_POLL_SOCKET;
mPollFD.reqevents = APR_POLLIN|APR_POLLERR|APR_POLLHUP; mPollFD.reqevents = APR_POLLIN|APR_POLLERR|APR_POLLHUP;
mPollFD.rtnevents = 0; mPollFD.rtnevents = 0;
@@ -664,6 +650,7 @@ void LLPluginProcessParent::updatePollset()
// delete the existing pollset. // delete the existing pollset.
apr_pollset_destroy(sPollSet); apr_pollset_destroy(sPollSet);
sPollSet = NULL; sPollSet = NULL;
sPollSetPool.destroy();
} }
std::list<LLPluginProcessParent*>::iterator iter; std::list<LLPluginProcessParent*>::iterator iter;
@@ -686,12 +673,14 @@ void LLPluginProcessParent::updatePollset()
{ {
#ifdef APR_POLLSET_NOCOPY #ifdef APR_POLLSET_NOCOPY
// The pollset doesn't exist yet. Create it now. // The pollset doesn't exist yet. Create it now.
apr_status_t status = apr_pollset_create(&sPollSet, count, gAPRPoolp, APR_POLLSET_NOCOPY); sPollSetPool.create();
apr_status_t status = apr_pollset_create(&sPollSet, count, sPollSetPool(), APR_POLLSET_NOCOPY);
if(status != APR_SUCCESS) if(status != APR_SUCCESS)
{ {
#endif // APR_POLLSET_NOCOPY #endif // APR_POLLSET_NOCOPY
LL_WARNS("PluginPoll") << "Couldn't create pollset. Falling back to non-pollset mode." << LL_ENDL; LL_WARNS("PluginPoll") << "Couldn't create pollset. Falling back to non-pollset mode." << LL_ENDL;
sPollSet = NULL; sPollSet = NULL;
sPollSetPool.destroy();
#ifdef APR_POLLSET_NOCOPY #ifdef APR_POLLSET_NOCOPY
} }
else else

View File

@@ -186,7 +186,9 @@ private:
static bool sUseReadThread; static bool sUseReadThread;
apr_pollfd_t mPollFD; apr_pollfd_t mPollFD;
AIAPRPool mPollFDPool;
static apr_pollset_t *sPollSet; static apr_pollset_t *sPollSet;
static AIAPRPool sPollSetPool;
static bool sPollsetNeedsRebuild; static bool sPollsetNeedsRebuild;
static LLMutex *sInstancesMutex; static LLMutex *sInstancesMutex;
static std::list<LLPluginProcessParent*> sInstances; static std::list<LLPluginProcessParent*> sInstances;

View File

@@ -201,7 +201,8 @@ bool LLPluginSharedMemory::create(size_t size)
mName += createName(); mName += createName();
mSize = size; mSize = size;
apr_status_t status = apr_shm_create( &(mImpl->mAprSharedMemory), mSize, mName.c_str(), gAPRPoolp ); mPool.create();
apr_status_t status = apr_shm_create( &(mImpl->mAprSharedMemory), mSize, mName.c_str(), mPool());
if(ll_apr_warn_status(status)) if(ll_apr_warn_status(status))
{ {
@@ -224,7 +225,7 @@ bool LLPluginSharedMemory::destroy(void)
} }
mImpl->mAprSharedMemory = NULL; mImpl->mAprSharedMemory = NULL;
} }
mPool.destroy();
return true; return true;
} }
@@ -233,7 +234,8 @@ bool LLPluginSharedMemory::attach(const std::string &name, size_t size)
mName = name; mName = name;
mSize = size; mSize = size;
apr_status_t status = apr_shm_attach( &(mImpl->mAprSharedMemory), mName.c_str(), gAPRPoolp ); mPool.create();
apr_status_t status = apr_shm_attach( &(mImpl->mAprSharedMemory), mName.c_str(), mPool() );
if(ll_apr_warn_status(status)) if(ll_apr_warn_status(status))
{ {
@@ -255,6 +257,7 @@ bool LLPluginSharedMemory::detach(void)
} }
mImpl->mAprSharedMemory = NULL; mImpl->mAprSharedMemory = NULL;
} }
mPool.destroy();
return true; return true;
} }

View File

@@ -35,6 +35,8 @@
#ifndef LL_LLPLUGINSHAREDMEMORY_H #ifndef LL_LLPLUGINSHAREDMEMORY_H
#define LL_LLPLUGINSHAREDMEMORY_H #define LL_LLPLUGINSHAREDMEMORY_H
#include "aiaprpool.h"
class LLPluginSharedMemoryPlatformImpl; class LLPluginSharedMemoryPlatformImpl;
/** /**
@@ -115,6 +117,7 @@ private:
bool close(void); bool close(void);
bool unlink(void); bool unlink(void);
AIAPRPool mPool;
std::string mName; std::string mName;
size_t mSize; size_t mSize;
void *mMappedAddress; void *mMappedAddress;

View File

@@ -183,8 +183,6 @@ int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdL
int main(int argc, char **argv) int main(int argc, char **argv)
#endif #endif
{ {
ll_init_apr();
// Set up llerror logging // Set up llerror logging
{ {
LLError::initForApplication("."); LLError::initForApplication(".");
@@ -400,8 +398,6 @@ int main(int argc, char **argv)
delete plugin; delete plugin;
ll_cleanup_apr();
return 0; return 0;
} }

View File

@@ -219,7 +219,7 @@ const S32 LLVFSFileBlock::SERIAL_SIZE = 34;
LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename, const BOOL read_only, const U32 presize, const BOOL remove_after_crash) LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename, const BOOL read_only, const U32 presize, const BOOL remove_after_crash)
: mRemoveAfterCrash(remove_after_crash) : mRemoveAfterCrash(remove_after_crash)
{ {
mDataMutex = new LLMutex(0); mDataMutex = new LLMutex;
S32 i; S32 i;
for (i = 0; i < VFSLOCK_COUNT; i++) for (i = 0; i < VFSLOCK_COUNT; i++)

View File

@@ -50,7 +50,7 @@ extern "C" {
#include <pulse/subscribe.h> #include <pulse/subscribe.h>
#include <pulse/glib-mainloop.h> // There's no special reason why we want the *glib* PA mainloop, but the generic polling implementation seems broken. #include <pulse/glib-mainloop.h> // There's no special reason why we want the *glib* PA mainloop, but the generic polling implementation seems broken.
#include "apr_pools.h" #include "aiaprpool.h"
#include "apr_dso.h" #include "apr_dso.h"
} }
@@ -66,7 +66,7 @@ extern "C" {
#undef LL_PA_SYM #undef LL_PA_SYM
static bool sSymsGrabbed = false; static bool sSymsGrabbed = false;
static apr_pool_t *sSymPADSOMemoryPool = NULL; static AIAPRPool sSymPADSOMemoryPool;
static apr_dso_handle_t *sSymPADSOHandleG = NULL; static apr_dso_handle_t *sSymPADSOHandleG = NULL;
bool grab_pa_syms(std::string pulse_dso_name) bool grab_pa_syms(std::string pulse_dso_name)
@@ -85,11 +85,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) #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 //attempt to load the shared library
apr_pool_create(&sSymPADSOMemoryPool, NULL); sSymPADSOMemoryPool.create();
if ( APR_SUCCESS == (rv = apr_dso_load(&sSymPADSOHandle, if ( APR_SUCCESS == (rv = apr_dso_load(&sSymPADSOHandle,
pulse_dso_name.c_str(), pulse_dso_name.c_str(),
sSymPADSOMemoryPool) )) sSymPADSOMemoryPool()) ))
{ {
INFOMSG("Found DSO: %s", pulse_dso_name.c_str()); INFOMSG("Found DSO: %s", pulse_dso_name.c_str());
@@ -132,11 +132,7 @@ void ungrab_pa_syms()
sSymPADSOHandleG = NULL; sSymPADSOHandleG = NULL;
} }
if ( sSymPADSOMemoryPool ) sSymPADSOMemoryPool.destroy();
{
apr_pool_destroy(sSymPADSOMemoryPool);
sSymPADSOMemoryPool = NULL;
}
// NULL-out all of the symbols we'd grabbed // NULL-out all of the symbols we'd grabbed
#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{ll##PASYM = NULL;}while(0) #define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{ll##PASYM = NULL;}while(0)

View File

@@ -857,7 +857,7 @@ bool LLAppViewer::mainLoop()
//------------------------------------------- //-------------------------------------------
// Create IO Pump to use for HTTP Requests. // Create IO Pump to use for HTTP Requests.
gServicePump = new LLPumpIO(gAPRPoolp); gServicePump = new LLPumpIO;
LLHTTPClient::setPump(*gServicePump); LLHTTPClient::setPump(*gServicePump);
LLCurl::setCAFile(gDirUtilp->getCAFile()); LLCurl::setCAFile(gDirUtilp->getCAFile());

View File

@@ -139,6 +139,7 @@ int main( int argc, char **argv )
} }
delete viewer_app_ptr; delete viewer_app_ptr;
viewer_app_ptr = NULL; viewer_app_ptr = NULL;
return 0; return 0;
} }

View File

@@ -119,6 +119,7 @@ int main( int argc, char **argv )
} }
delete viewer_app_ptr; delete viewer_app_ptr;
viewer_app_ptr = NULL; viewer_app_ptr = NULL;
return 0; return 0;
} }

View File

@@ -68,8 +68,7 @@ LLConsole::LLConsole(const std::string& name, const LLRect &rect,
mFadeTime(persist_time - FADE_DURATION), mFadeTime(persist_time - FADE_DURATION),
mFont(LLFontGL::getFontSansSerif()), mFont(LLFontGL::getFontSansSerif()),
mConsoleWidth(0), mConsoleWidth(0),
mConsoleHeight(0), mConsoleHeight(0)
mQueueMutex(NULL)
{ {
mTimer.reset(); mTimer.reset();

View File

@@ -743,9 +743,6 @@ void LLTextureCacheWorker::endWork(S32 param, bool aborted)
LLTextureCache::LLTextureCache(bool threaded) LLTextureCache::LLTextureCache(bool threaded)
: LLWorkerThread("TextureCache", threaded), : LLWorkerThread("TextureCache", threaded),
mWorkersMutex(NULL),
mHeaderMutex(NULL),
mListMutex(NULL),
mHeaderAPRFile(NULL), mHeaderAPRFile(NULL),
mReadOnly(TRUE), //do not allow to change the texture cache until setReadOnly() is called. mReadOnly(TRUE), //do not allow to change the texture cache until setReadOnly() is called.
mTexturesSizeTotal(0), mTexturesSizeTotal(0),

View File

@@ -143,9 +143,6 @@ protected:
std::string getTextureFileName(const LLUUID& id); std::string getTextureFileName(const LLUUID& id);
void addCompleted(Responder* responder, bool success); void addCompleted(Responder* responder, bool success);
protected:
//void setFileAPRPool(apr_pool_t* pool) { mFileAPRPool = pool ; }
private: private:
void setDirNames(ELLPath location); void setDirNames(ELLPath location);
void readHeaderCache(); void readHeaderCache();

View File

@@ -425,7 +425,7 @@ class SGHostBlackList{
static void lock() { static void lock() {
if (!sMutex) if (!sMutex)
sMutex = new LLMutex(0); sMutex = new LLMutex;
sMutex->lock(); sMutex->lock();
} }
@@ -767,7 +767,6 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
mRetryAttempt(0), mRetryAttempt(0),
mActiveCount(0), mActiveCount(0),
mGetStatus(0), mGetStatus(0),
mWorkMutex(NULL),
mFirstPacket(0), mFirstPacket(0),
mLastPacket(-1), mLastPacket(-1),
mTotalPackets(0), mTotalPackets(0),
@@ -1943,8 +1942,6 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
mDebugPause(FALSE), mDebugPause(FALSE),
mPacketCount(0), mPacketCount(0),
mBadPacketCount(0), mBadPacketCount(0),
mQueueMutex(getAPRPool()),
mNetworkQueueMutex(getAPRPool()),
mTextureCache(cache), mTextureCache(cache),
mImageDecodeThread(imagedecodethread), mImageDecodeThread(imagedecodethread),
mTextureBandwidth(0), mTextureBandwidth(0),

View File

@@ -164,7 +164,7 @@
#include "llinstantmessage.h" #include "llinstantmessage.h"
#include "llinvite.h" #include "llinvite.h"
//#include "llloginflags.h" //#include "llloginflags.h"
#include "llmail.h" //#include "llmail.h"
#include "llmessagethrottle.h" #include "llmessagethrottle.h"
#include "llnamevalue.h" #include "llnamevalue.h"
#include "llpacketack.h" #include "llpacketack.h"

View File

@@ -1781,7 +1781,7 @@ void LLVoiceClient::stateMachine()
if(!mSocket) if(!mSocket)
{ {
mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); mSocket = LLSocket::create(LLSocket::STREAM_TCP);
} }
mConnected = mSocket->blockingConnect(mDaemonHost); mConnected = mSocket->blockingConnect(mDaemonHost);

View File

@@ -184,8 +184,8 @@ void LLWatchdog::init(killer_event_callback func)
mKillerCallback = func; mKillerCallback = func;
if(!mSuspectsAccessMutex && !mTimer) if(!mSuspectsAccessMutex && !mTimer)
{ {
mSuspectsAccessMutex = new LLMutex(NULL); mSuspectsAccessMutex = new LLMutex;
mTimer = new LLWatchdogTimerThread(); mTimer = new LLWatchdogTimerThread;
mTimer->setSleepTime(WATCHDOG_SLEEP_TIME_USEC / 1000); mTimer->setSleepTime(WATCHDOG_SLEEP_TIME_USEC / 1000);
mLastClockCount = LLTimer::getTotalTime(); mLastClockCount = LLTimer::getTotalTime();

View File

@@ -35,7 +35,6 @@
#include "linden_common.h" #include "linden_common.h"
#include "lltut.h" #include "lltut.h"
#include "llapr.h"
#include "llmessagetemplate.h" #include "llmessagetemplate.h"
#include "llquaternion.h" #include "llquaternion.h"
#include "lltemplatemessagebuilder.h" #include "lltemplatemessagebuilder.h"
@@ -59,7 +58,6 @@ namespace tut
static bool init = false; static bool init = false;
if(! init) if(! init)
{ {
ll_init_apr();
const F32 circuit_heartbeat_interval=5; const F32 circuit_heartbeat_interval=5;
const F32 circuit_timeout=100; const F32 circuit_timeout=100;

View File

@@ -35,7 +35,6 @@
#include "linden_common.h" #include "linden_common.h"
#include "lltut.h" #include "lltut.h"
#include "llapr.h"
#include "llmessageconfig.h" #include "llmessageconfig.h"
#include "llsdserialize.h" #include "llsdserialize.h"
#include "llversionserver.h" #include "llversionserver.h"
@@ -68,7 +67,6 @@ namespace tut
static bool init = false; static bool init = false;
if(!init) if(!init)
{ {
ll_init_apr();
//init_prehash_data(); //init_prehash_data();
init = true; init = true;
} }

View File

@@ -43,8 +43,8 @@
#include "linden_common.h" #include "linden_common.h"
#include "llerrorcontrol.h" #include "llerrorcontrol.h"
#include "lltut.h" #include "lltut.h"
#include "aiaprpool.h"
#include "apr_pools.h"
#include "apr_getopt.h" #include "apr_getopt.h"
extern void ll_init_apr(); extern void ll_init_apr();
@@ -250,17 +250,12 @@ int main(int argc, char **argv)
ctype_workaround(); ctype_workaround();
#endif #endif
ll_init_apr(); AIAPRPool pool;
apr_pool_t* pool = NULL; pool.create();
if(APR_SUCCESS != apr_pool_create(&pool, NULL))
{
std::cerr << "Unable to initialize pool" << std::endl;
return 1;
}
apr_getopt_t* os = NULL; 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 pool" << std::endl; std::cerr << "Unable to initialize the arguments for parsing by apr_getopt()." << std::endl;
return 1; return 1;
} }
@@ -362,6 +357,5 @@ int main(int argc, char **argv)
s.close(); s.close();
} }
apr_terminate();
return 0; return 0;
} }