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

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

View File

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

View File

@@ -47,7 +47,7 @@ LLPluginProcessChild::LLPluginProcessChild()
{
mState = STATE_UNINITIALIZED;
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
mCPUElapsed = 0.0f;
mBlockingRequest = false;

View File

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

View File

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

View File

@@ -201,7 +201,8 @@ bool LLPluginSharedMemory::create(size_t size)
mName += createName();
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))
{
@@ -224,7 +225,7 @@ bool LLPluginSharedMemory::destroy(void)
}
mImpl->mAprSharedMemory = NULL;
}
mPool.destroy();
return true;
}
@@ -233,7 +234,8 @@ bool LLPluginSharedMemory::attach(const std::string &name, size_t size)
mName = name;
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))
{
@@ -255,6 +257,7 @@ bool LLPluginSharedMemory::detach(void)
}
mImpl->mAprSharedMemory = NULL;
}
mPool.destroy();
return true;
}

View File

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

View File

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