summaryrefslogtreecommitdiff
path: root/indra/llplugin
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llplugin')
-rw-r--r--indra/llplugin/llpluginclassmedia.cpp8
-rw-r--r--indra/llplugin/llpluginclassmedia.h5
-rw-r--r--indra/llplugin/llplugininstance.cpp6
-rw-r--r--indra/llplugin/llplugininstance.h4
-rw-r--r--indra/llplugin/llpluginmessagepipe.cpp53
-rw-r--r--indra/llplugin/llpluginmessagepipe.h3
-rw-r--r--indra/llplugin/llpluginprocesschild.cpp2
-rw-r--r--indra/llplugin/llpluginprocessparent.cpp104
-rw-r--r--indra/llplugin/llpluginprocessparent.h24
-rw-r--r--indra/llplugin/llpluginsharedmemory.cpp9
-rw-r--r--indra/llplugin/llpluginsharedmemory.h3
-rw-r--r--indra/llplugin/slplugin/slplugin.cpp4
12 files changed, 131 insertions, 94 deletions
diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index c53857fcee..dbd96673a1 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -1239,6 +1239,14 @@ void LLPluginClassMedia::focus(bool focused)
sendMessage(message);
}
+void LLPluginClassMedia::set_page_zoom_factor( double factor )
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_page_zoom_factor");
+
+ message.setValueReal("factor", factor);
+ sendMessage(message);
+}
+
void LLPluginClassMedia::clear_cache()
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cache");
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index 1f548f8cc0..5fe8254331 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -41,7 +41,7 @@ class LLPluginClassMedia : public LLPluginProcessParentOwner
LOG_CLASS(LLPluginClassMedia);
public:
LLPluginClassMedia(LLPluginClassMediaOwner *owner);
- ~LLPluginClassMedia();
+ virtual ~LLPluginClassMedia();
// local initialization, called by the media manager when creating a source
bool init(const std::string &launcher_filename,
@@ -202,6 +202,7 @@ public:
bool pluginSupportsMediaBrowser(void);
void focus(bool focused);
+ void set_page_zoom_factor( double factor );
void clear_cache();
void clear_cookies();
void set_cookies(const std::string &cookies);
@@ -269,7 +270,7 @@ public:
std::string getHoverText() const { return mHoverText; };
std::string getHoverLink() const { return mHoverLink; };
- std::string getMediaName() const { return mMediaName; };
+ const std::string& getMediaName() const { return mMediaName; };
std::string getMediaDescription() const { return mMediaDescription; };
// Crash the plugin. If you use this outside of a testbed, you will be punished.
diff --git a/indra/llplugin/llplugininstance.cpp b/indra/llplugin/llplugininstance.cpp
index e8efb233ff..7cde82a20e 100644
--- a/indra/llplugin/llplugininstance.cpp
+++ b/indra/llplugin/llplugininstance.cpp
@@ -29,7 +29,8 @@
#include "linden_common.h"
#include "llplugininstance.h"
-#include "llthread.h" // Needed for LLThread::tldata().mRootPool
+
+#include "llapr.h"
#if LL_WINDOWS
#include "direct.h" // needed for _chdir()
@@ -51,7 +52,6 @@ const char *LLPluginInstance::PLUGIN_INIT_FUNCTION_NAME = "LLPluginInitEntryPoin
* @param[in] owner Plugin instance. TODO:DOC is this a good description of what "owner" is?
*/
LLPluginInstance::LLPluginInstance(LLPluginInstanceMessageListener *owner) :
- mDSOHandlePool(LLThread::tldata().mRootPool),
mDSOHandle(NULL),
mPluginUserData(NULL),
mPluginSendMessageFunction(NULL)
@@ -97,7 +97,7 @@ int LLPluginInstance::load(const std::string& plugin_dir, std::string &plugin_fi
int result = apr_dso_load(&mDSOHandle,
plugin_file.c_str(),
- mDSOHandlePool());
+ gAPRPoolp);
if(result != APR_SUCCESS)
{
char buf[1024];
diff --git a/indra/llplugin/llplugininstance.h b/indra/llplugin/llplugininstance.h
index ee28f68e83..e6926c3e37 100644
--- a/indra/llplugin/llplugininstance.h
+++ b/indra/llplugin/llplugininstance.h
@@ -30,7 +30,6 @@
#include "llstring.h"
#include "llapr.h"
-#include "llaprpool.h"
#include "apr_dso.h"
@@ -40,7 +39,7 @@
class LLPluginInstanceMessageListener
{
public:
- ~LLPluginInstanceMessageListener();
+ virtual ~LLPluginInstanceMessageListener();
/** Plugin receives message from plugin loader shell. */
virtual void receivePluginMessage(const std::string &message) = 0;
};
@@ -89,7 +88,6 @@ private:
static void staticReceiveMessage(const char *message_string, void **user_data);
void receiveMessage(const char *message_string);
- LLAPRPool mDSOHandlePool;
apr_dso_handle_t *mDSOHandle;
void *mPluginUserData;
diff --git a/indra/llplugin/llpluginmessagepipe.cpp b/indra/llplugin/llpluginmessagepipe.cpp
index dd47300b9c..091e93ea4b 100644
--- a/indra/llplugin/llpluginmessagepipe.cpp
+++ b/indra/llplugin/llpluginmessagepipe.cpp
@@ -92,10 +92,12 @@ void LLPluginMessagePipeOwner::killMessagePipe(void)
}
LLPluginMessagePipe::LLPluginMessagePipe(LLPluginMessagePipeOwner *owner, LLSocket::ptr_t socket):
+ mInputMutex(gAPRPoolp),
+ mOutputMutex(gAPRPoolp),
+ mOutputStartIndex(0),
mOwner(owner),
mSocket(socket)
{
-
mOwner->setMessagePipe(this);
}
@@ -111,6 +113,14 @@ bool LLPluginMessagePipe::addMessage(const std::string &message)
{
// queue the message for later output
LLMutexLock lock(&mOutputMutex);
+
+ // If we're starting to use up too much memory, clear
+ if (mOutputStartIndex > 1024 * 1024)
+ {
+ mOutput = mOutput.substr(mOutputStartIndex);
+ mOutputStartIndex = 0;
+ }
+
mOutput += message;
mOutput += MESSAGE_DELIMITER; // message separator
@@ -163,35 +173,44 @@ bool LLPluginMessagePipe::pumpOutput()
if(mSocket)
{
apr_status_t status;
- apr_size_t size;
+ apr_size_t in_size, out_size;
LLMutexLock lock(&mOutputMutex);
- if(!mOutput.empty())
+
+ const char * output_data = &(mOutput.data()[mOutputStartIndex]);
+ if(*output_data != '\0')
{
// write any outgoing messages
- size = (apr_size_t)mOutput.size();
+ in_size = (apr_size_t) (mOutput.size() - mOutputStartIndex);
+ out_size = in_size;
setSocketTimeout(0);
// LL_INFOS("Plugin") << "before apr_socket_send, size = " << size << LL_ENDL;
- status = apr_socket_send(
- mSocket->getSocket(),
- (const char*)mOutput.data(),
- &size);
+ status = apr_socket_send(mSocket->getSocket(),
+ output_data,
+ &out_size);
// LL_INFOS("Plugin") << "after apr_socket_send, size = " << size << LL_ENDL;
- if(status == APR_SUCCESS)
+ if((status == APR_SUCCESS) || APR_STATUS_IS_EAGAIN(status))
{
- // success
- mOutput = mOutput.substr(size);
- }
- else if(APR_STATUS_IS_EAGAIN(status))
- {
- // Socket buffer is full...
- // remove the written part from the buffer and try again later.
- mOutput = mOutput.substr(size);
+ // Success or Socket buffer is full...
+
+ // If we've pumped the entire string, clear it
+ if (out_size == in_size)
+ {
+ mOutputStartIndex = 0;
+ mOutput.clear();
+ }
+ else
+ {
+ llassert(in_size > out_size);
+
+ // Remove the written part from the buffer and try again later.
+ mOutputStartIndex += out_size;
+ }
}
else if(APR_STATUS_IS_EOF(status))
{
diff --git a/indra/llplugin/llpluginmessagepipe.h b/indra/llplugin/llpluginmessagepipe.h
index beb942c0fe..c3498beac0 100644
--- a/indra/llplugin/llpluginmessagepipe.h
+++ b/indra/llplugin/llpluginmessagepipe.h
@@ -40,7 +40,7 @@ class LLPluginMessagePipeOwner
LOG_CLASS(LLPluginMessagePipeOwner);
public:
LLPluginMessagePipeOwner();
- ~LLPluginMessagePipeOwner();
+ virtual ~LLPluginMessagePipeOwner();
// called with incoming messages
virtual void receiveMessageRaw(const std::string &message) = 0;
@@ -86,6 +86,7 @@ protected:
std::string mInput;
LLMutex mOutputMutex;
std::string mOutput;
+ std::string::size_type mOutputStartIndex;
LLPluginMessagePipeOwner *mOwner;
LLSocket::ptr_t mSocket;
diff --git a/indra/llplugin/llpluginprocesschild.cpp b/indra/llplugin/llpluginprocesschild.cpp
index fd63fdde81..f8a282184e 100644
--- a/indra/llplugin/llpluginprocesschild.cpp
+++ b/indra/llplugin/llpluginprocesschild.cpp
@@ -40,7 +40,7 @@ LLPluginProcessChild::LLPluginProcessChild()
{
mState = STATE_UNINITIALIZED;
mInstance = NULL;
- mSocket = LLSocket::create(LLSocket::STREAM_TCP);
+ mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP);
mSleepTime = PLUGIN_IDLE_SECONDS; // default: send idle messages at 100Hz
mCPUElapsed = 0.0f;
mBlockingRequest = false;
diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp
index 7aec72731e..f10eaee5b4 100644
--- a/indra/llplugin/llpluginprocessparent.cpp
+++ b/indra/llplugin/llpluginprocessparent.cpp
@@ -31,9 +31,9 @@
#include "llpluginprocessparent.h"
#include "llpluginmessagepipe.h"
#include "llpluginmessageclasses.h"
+#include "stringize.h"
#include "llapr.h"
-#include "llscopedvolatileaprpool.h"
//virtual
LLPluginProcessParentOwner::~LLPluginProcessParentOwner()
@@ -43,7 +43,6 @@ LLPluginProcessParentOwner::~LLPluginProcessParentOwner()
bool LLPluginProcessParent::sUseReadThread = false;
apr_pollset_t *LLPluginProcessParent::sPollSet = NULL;
-LLAPRPool LLPluginProcessParent::sPollSetPool;
bool LLPluginProcessParent::sPollsetNeedsRebuild = false;
LLMutex *LLPluginProcessParent::sInstancesMutex;
std::list<LLPluginProcessParent*> LLPluginProcessParent::sInstances;
@@ -54,7 +53,7 @@ class LLPluginProcessParentPollThread: public LLThread
{
public:
LLPluginProcessParentPollThread() :
- LLThread("LLPluginProcessParentPollThread")
+ LLThread("LLPluginProcessParentPollThread", gAPRPoolp)
{
}
protected:
@@ -79,11 +78,12 @@ protected:
};
-LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner* owner)
+LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner):
+ mIncomingQueueMutex(gAPRPoolp)
{
if(!sInstancesMutex)
{
- sInstancesMutex = new LLMutex;
+ sInstancesMutex = new LLMutex(gAPRPoolp);
}
mOwner = owner;
@@ -96,7 +96,6 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner* owner)
mBlocked = false;
mPolledInput = false;
mPollFD.client_data = NULL;
- mPollFDPool.create();
mPluginLaunchTimeout = 60.0f;
mPluginLockupTimeout = 15.0f;
@@ -136,7 +135,10 @@ LLPluginProcessParent::~LLPluginProcessParent()
mSharedMemoryRegions.erase(iter);
}
- mProcess.kill();
+ if (mProcess)
+ {
+ mProcess->kill();
+ }
killSockets();
}
@@ -161,8 +163,8 @@ void LLPluginProcessParent::errorState(void)
void LLPluginProcessParent::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug)
{
- mProcess.setExecutable(launcher_filename);
- mProcess.setWorkingDirectory(plugin_dir);
+ mProcessParams.executable = launcher_filename;
+ mProcessParams.cwd = plugin_dir;
mPluginFile = plugin_filename;
mPluginDir = plugin_dir;
mCPUUsage = 0.0f;
@@ -173,28 +175,44 @@ void LLPluginProcessParent::init(const std::string &launcher_filename, const std
bool LLPluginProcessParent::accept()
{
bool result = false;
+
apr_status_t status = APR_EGENERAL;
+ apr_socket_t *new_socket = NULL;
+
+ status = apr_socket_accept(
+ &new_socket,
+ mListenSocket->getSocket(),
+ gAPRPoolp);
- mSocket = LLSocket::create(status, mListenSocket);
if(status == APR_SUCCESS)
{
// llinfos << "SUCCESS" << llendl;
// Success. Create a message pipe on the new socket
+
+ // we MUST create a new pool for the LLSocket, since it will take ownership of it and delete it in its destructor!
+ apr_pool_t* new_pool = NULL;
+ status = apr_pool_create(&new_pool, gAPRPoolp);
+
+ mSocket = LLSocket::create(new_socket, new_pool);
new LLPluginMessagePipe(this, mSocket);
result = true;
}
+ else if(APR_STATUS_IS_EAGAIN(status))
+ {
+// llinfos << "EAGAIN" << llendl;
+
+ // No incoming connections. This is not an error.
+ status = APR_SUCCESS;
+ }
else
{
- mSocket.reset();
- // EAGAIN means "No incoming connections". This is not an error.
- if (!APR_STATUS_IS_EAGAIN(status))
- {
- // Some other error.
- ll_apr_warn_status(status);
- errorState();
- }
+// llinfos << "Error:" << llendl;
+ ll_apr_warn_status(status);
+
+ // Some other error.
+ errorState();
}
return result;
@@ -260,10 +278,10 @@ void LLPluginProcessParent::idle(void)
case STATE_INITIALIZED:
{
+
apr_status_t status = APR_SUCCESS;
- LLScopedVolatileAPRPool addr_pool;
apr_sockaddr_t* addr = NULL;
- mListenSocket = LLSocket::create(LLSocket::STREAM_TCP);
+ mListenSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP);
mBoundPort = 0;
// This code is based on parts of LLSocket::create() in lliosocket.cpp.
@@ -274,7 +292,7 @@ void LLPluginProcessParent::idle(void)
APR_INET,
0, // port 0 = ephemeral ("find me a port")
0,
- addr_pool);
+ gAPRPoolp);
if(ll_apr_warn_status(status))
{
@@ -357,10 +375,8 @@ void LLPluginProcessParent::idle(void)
// Launch the plugin process.
// Only argument to the launcher is the port number we're listening on
- std::stringstream stream;
- stream << mBoundPort;
- mProcess.addArgument(stream.str());
- if(mProcess.launch() != 0)
+ mProcessParams.args.add(stringize(mBoundPort));
+ if (! (mProcess = LLProcess::create(mProcessParams)))
{
errorState();
}
@@ -374,19 +390,18 @@ void LLPluginProcessParent::idle(void)
// The command we're constructing would look like this on the command line:
// osascript -e 'tell application "Terminal"' -e 'set win to do script "gdb -pid 12345"' -e 'do script "continue" in win' -e 'end tell'
- std::stringstream cmd;
-
- mDebugger.setExecutable("/usr/bin/osascript");
- mDebugger.addArgument("-e");
- mDebugger.addArgument("tell application \"Terminal\"");
- mDebugger.addArgument("-e");
- cmd << "set win to do script \"gdb -pid " << mProcess.getProcessID() << "\"";
- mDebugger.addArgument(cmd.str());
- mDebugger.addArgument("-e");
- mDebugger.addArgument("do script \"continue\" in win");
- mDebugger.addArgument("-e");
- mDebugger.addArgument("end tell");
- mDebugger.launch();
+ LLProcess::Params params;
+ params.executable = "/usr/bin/osascript";
+ params.args.add("-e");
+ params.args.add("tell application \"Terminal\"");
+ params.args.add("-e");
+ params.args.add(STRINGIZE("set win to do script \"gdb -pid "
+ << mProcess->getProcessID() << "\""));
+ params.args.add("-e");
+ params.args.add("do script \"continue\" in win");
+ params.args.add("-e");
+ params.args.add("end tell");
+ mDebugger = LLProcess::create(params);
#endif
}
@@ -456,7 +471,7 @@ void LLPluginProcessParent::idle(void)
break;
case STATE_EXITING:
- if(!mProcess.isRunning())
+ if (! mProcess->isRunning())
{
setState(STATE_CLEANUP);
}
@@ -484,7 +499,7 @@ void LLPluginProcessParent::idle(void)
break;
case STATE_CLEANUP:
- mProcess.kill();
+ mProcess->kill();
killSockets();
setState(STATE_DONE);
break;
@@ -587,7 +602,7 @@ void LLPluginProcessParent::setMessagePipe(LLPluginMessagePipe *message_pipe)
if(message_pipe != NULL)
{
// Set up the apr_pollfd_t
- mPollFD.p = mPollFDPool();
+ mPollFD.p = gAPRPoolp;
mPollFD.desc_type = APR_POLL_SOCKET;
mPollFD.reqevents = APR_POLLIN|APR_POLLERR|APR_POLLHUP;
mPollFD.rtnevents = 0;
@@ -634,7 +649,6 @@ void LLPluginProcessParent::updatePollset()
// delete the existing pollset.
apr_pollset_destroy(sPollSet);
sPollSet = NULL;
- sPollSetPool.destroy();
}
std::list<LLPluginProcessParent*>::iterator iter;
@@ -657,14 +671,12 @@ void LLPluginProcessParent::updatePollset()
{
#ifdef APR_POLLSET_NOCOPY
// The pollset doesn't exist yet. Create it now.
- sPollSetPool.create();
- apr_status_t status = apr_pollset_create(&sPollSet, count, sPollSetPool(), APR_POLLSET_NOCOPY);
+ apr_status_t status = apr_pollset_create(&sPollSet, count, gAPRPoolp, APR_POLLSET_NOCOPY);
if(status != APR_SUCCESS)
{
#endif // APR_POLLSET_NOCOPY
LL_WARNS("PluginPoll") << "Couldn't create pollset. Falling back to non-pollset mode." << LL_ENDL;
sPollSet = NULL;
- sPollSetPool.destroy();
#ifdef APR_POLLSET_NOCOPY
}
else
@@ -1066,7 +1078,7 @@ bool LLPluginProcessParent::pluginLockedUpOrQuit()
{
bool result = false;
- if(!mProcess.isRunning())
+ if (! mProcess->isRunning())
{
LL_WARNS("Plugin") << "child exited" << LL_ENDL;
result = true;
diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h
index 74b7e9f50c..990fc5cbae 100644
--- a/indra/llplugin/llpluginprocessparent.h
+++ b/indra/llplugin/llpluginprocessparent.h
@@ -30,18 +30,19 @@
#define LL_LLPLUGINPROCESSPARENT_H
#include "llapr.h"
-#include "llprocesslauncher.h"
+#include "llprocess.h"
#include "llpluginmessage.h"
#include "llpluginmessagepipe.h"
#include "llpluginsharedmemory.h"
#include "lliosocket.h"
#include "llthread.h"
+#include "llsd.h"
class LLPluginProcessParentOwner
{
public:
- ~LLPluginProcessParentOwner();
+ virtual ~LLPluginProcessParentOwner();
virtual void receivePluginMessage(const LLPluginMessage &message) = 0;
virtual bool receivePluginMessageEarly(const LLPluginMessage &message) {return false;};
// This will only be called when the plugin has died unexpectedly
@@ -139,26 +140,27 @@ private:
};
EState mState;
void setState(EState state);
-
+
bool pluginLockedUp();
bool pluginLockedUpOrQuit();
bool accept();
-
+
LLSocket::ptr_t mListenSocket;
LLSocket::ptr_t mSocket;
U32 mBoundPort;
-
- LLProcessLauncher mProcess;
-
+
+ LLProcess::Params mProcessParams;
+ LLProcessPtr mProcess;
+
std::string mPluginFile;
std::string mPluginDir;
LLPluginProcessParentOwner *mOwner;
-
+
typedef std::map<std::string, LLPluginSharedMemory*> sharedMemoryRegionsType;
sharedMemoryRegionsType mSharedMemoryRegions;
-
+
LLSD mMessageClassVersions;
std::string mPluginVersionString;
@@ -171,16 +173,14 @@ private:
bool mBlocked;
bool mPolledInput;
- LLProcessLauncher mDebugger;
+ LLProcessPtr mDebugger;
F32 mPluginLaunchTimeout; // Somewhat longer timeout for initial launch.
F32 mPluginLockupTimeout; // If we don't receive a heartbeat in this many seconds, we declare the plugin locked up.
static bool sUseReadThread;
apr_pollfd_t mPollFD;
- LLAPRPool mPollFDPool;
static apr_pollset_t *sPollSet;
- static LLAPRPool sPollSetPool;
static bool sPollsetNeedsRebuild;
static LLMutex *sInstancesMutex;
static std::list<LLPluginProcessParent*> sInstances;
diff --git a/indra/llplugin/llpluginsharedmemory.cpp b/indra/llplugin/llpluginsharedmemory.cpp
index e2ff645a9c..63ff5085c6 100644
--- a/indra/llplugin/llpluginsharedmemory.cpp
+++ b/indra/llplugin/llpluginsharedmemory.cpp
@@ -187,8 +187,7 @@ bool LLPluginSharedMemory::create(size_t size)
mName += createName();
mSize = size;
- mPool.create();
- apr_status_t status = apr_shm_create( &(mImpl->mAprSharedMemory), mSize, mName.c_str(), mPool());
+ apr_status_t status = apr_shm_create( &(mImpl->mAprSharedMemory), mSize, mName.c_str(), gAPRPoolp );
if(ll_apr_warn_status(status))
{
@@ -211,7 +210,7 @@ bool LLPluginSharedMemory::destroy(void)
}
mImpl->mAprSharedMemory = NULL;
}
- mPool.destroy();
+
return true;
}
@@ -220,8 +219,7 @@ bool LLPluginSharedMemory::attach(const std::string &name, size_t size)
mName = name;
mSize = size;
- mPool.create();
- apr_status_t status = apr_shm_attach( &(mImpl->mAprSharedMemory), mName.c_str(), mPool() );
+ apr_status_t status = apr_shm_attach( &(mImpl->mAprSharedMemory), mName.c_str(), gAPRPoolp );
if(ll_apr_warn_status(status))
{
@@ -243,7 +241,6 @@ bool LLPluginSharedMemory::detach(void)
}
mImpl->mAprSharedMemory = NULL;
}
- mPool.destroy();
return true;
}
diff --git a/indra/llplugin/llpluginsharedmemory.h b/indra/llplugin/llpluginsharedmemory.h
index 84b7a58c32..c6cd49cabb 100644
--- a/indra/llplugin/llpluginsharedmemory.h
+++ b/indra/llplugin/llpluginsharedmemory.h
@@ -28,8 +28,6 @@
#ifndef LL_LLPLUGINSHAREDMEMORY_H
#define LL_LLPLUGINSHAREDMEMORY_H
-#include "llaprpool.h"
-
class LLPluginSharedMemoryPlatformImpl;
/**
@@ -110,7 +108,6 @@ private:
bool close(void);
bool unlink(void);
- LLAPRPool mPool;
std::string mName;
size_t mSize;
void *mMappedAddress;
diff --git a/indra/llplugin/slplugin/slplugin.cpp b/indra/llplugin/slplugin/slplugin.cpp
index ff86e4e135..516a58db88 100644
--- a/indra/llplugin/slplugin/slplugin.cpp
+++ b/indra/llplugin/slplugin/slplugin.cpp
@@ -176,6 +176,8 @@ int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdL
int main(int argc, char **argv)
#endif
{
+ ll_init_apr();
+
// Set up llerror logging
{
LLError::initForApplication(".");
@@ -391,6 +393,8 @@ int main(int argc, char **argv)
delete plugin;
+ ll_cleanup_apr();
+
return 0;
}