summaryrefslogtreecommitdiff
path: root/indra/llplugin
diff options
context:
space:
mode:
authorAndrey Kleshchev <andreykproductengine@lindenlab.com>2021-05-21 20:08:26 +0300
committerAndrey Kleshchev <andreykproductengine@lindenlab.com>2021-05-25 03:31:50 +0300
commitd875f809002706e284e6a5da30fd911723e88c44 (patch)
tree598019d2e83f6926faf34aa3961cf646379ce6a4 /indra/llplugin
parentfa26f5eaa2cb1a0152fe681e9baa292626564caf (diff)
SL-14988 Plugin process creation can cause a notiecable delay
Diffstat (limited to 'indra/llplugin')
-rw-r--r--indra/llplugin/llpluginprocessparent.cpp104
-rw-r--r--indra/llplugin/llpluginprocessparent.h8
2 files changed, 104 insertions, 8 deletions
diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp
index f4bd944387..a2827e2eed 100644
--- a/indra/llplugin/llpluginprocessparent.cpp
+++ b/indra/llplugin/llpluginprocessparent.cpp
@@ -79,8 +79,29 @@ protected:
};
+
+class LLPluginProcessCreationThread : public LLThread
+{
+public:
+ LLPluginProcessCreationThread(LLPluginProcessParent *parent) :
+ LLThread("LLPluginProcessCreationThread", gAPRPoolp),
+ pParent(parent)
+ {
+ }
+protected:
+ // Inherited from LLThread, should run once
+ /*virtual*/ void run(void)
+ {
+ pParent->createPluginProcess();
+ }
+private:
+ LLPluginProcessParent *pParent;
+
+};
+
LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner):
- mIncomingQueueMutex()
+ mIncomingQueueMutex(),
+ pProcessCreationThread(NULL)
{
if(!sInstancesMutex)
{
@@ -109,6 +130,18 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner):
LLPluginProcessParent::~LLPluginProcessParent()
{
LL_DEBUGS("Plugin") << "destructor" << LL_ENDL;
+ if (pProcessCreationThread)
+ {
+ if (!pProcessCreationThread->isStopped())
+ {
+ // Shouldn't happen at this stage
+ LL_WARNS("Plugin") << "Shutting down active pProcessCreationThread" << LL_ENDL;
+ pProcessCreationThread->shutdown();
+ ms_sleep(20);
+ }
+ delete pProcessCreationThread;
+ pProcessCreationThread = NULL;
+ }
// Destroy any remaining shared memory regions
sharedMemoryRegionsType::iterator iter;
@@ -313,6 +346,35 @@ bool LLPluginProcessParent::accept()
return result;
}
+bool LLPluginProcessParent::createPluginProcess()
+{
+ if (!mProcess)
+ {
+ // Only argument to the launcher is the port number we're listening on
+ mProcessParams.args.add(stringize(mBoundPort));
+ mProcess = LLProcess::create(mProcessParams);
+ return mProcess != NULL;
+ }
+
+ return false;
+}
+
+void LLPluginProcessParent::clearProcessCreationThread()
+{
+ if (pProcessCreationThread)
+ {
+ if (!pProcessCreationThread->isStopped())
+ {
+ pProcessCreationThread->shutdown();
+ }
+ else
+ {
+ delete pProcessCreationThread;
+ pProcessCreationThread = NULL;
+ }
+ }
+}
+
void LLPluginProcessParent::idle(void)
{
bool idle_again;
@@ -472,14 +534,30 @@ void LLPluginProcessParent::idle(void)
case STATE_LISTENING:
{
// Launch the plugin process.
+ if (mDebug && !pProcessCreationThread)
+ {
+ createPluginProcess();
+ if (!mProcess)
+ {
+ errorState();
+ }
+ }
+ else if (pProcessCreationThread == NULL)
+ {
+ // exe plugin process allocation can be hindered by a number
+ // of factors, don't hold whole viewer because of it, use thread
+ pProcessCreationThread = new LLPluginProcessCreationThread(this);
+ pProcessCreationThread->start();
+ }
+ else if (!mProcess && pProcessCreationThread->isStopped())
+ {
+ delete pProcessCreationThread;
+ pProcessCreationThread = NULL;
+ errorState();
+ }
+
- // Only argument to the launcher is the port number we're listening on
- mProcessParams.args.add(stringize(mBoundPort));
- if (! (mProcess = LLProcess::create(mProcessParams)))
- {
- errorState();
- }
- else
+ if (mProcess)
{
if(mDebug)
{
@@ -508,6 +586,15 @@ void LLPluginProcessParent::idle(void)
// This will allow us to time out if the process never starts.
mHeartbeat.start();
mHeartbeat.setTimerExpirySec(mPluginLaunchTimeout);
+
+ // pProcessCreationThread should have stopped by this point,
+ // but check just in case it paused on statistics sync
+ if (pProcessCreationThread && pProcessCreationThread->isStopped())
+ {
+ delete pProcessCreationThread;
+ pProcessCreationThread = NULL;
+ }
+
setState(STATE_LAUNCHED);
}
}
@@ -610,6 +697,7 @@ void LLPluginProcessParent::idle(void)
killSockets();
setState(STATE_DONE);
dirtyPollSet();
+ clearProcessCreationThread();
break;
case STATE_DONE:
diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h
index df1630255c..1893c9e657 100644
--- a/indra/llplugin/llpluginprocessparent.h
+++ b/indra/llplugin/llpluginprocessparent.h
@@ -69,6 +69,11 @@ public:
const std::string &plugin_filename,
bool debug);
+ // Creates a process
+ // returns true if process already exists or if created,
+ // false if failed to create
+ bool createPluginProcess();
+
void idle(void);
// returns true if the plugin is on its way to steady state
@@ -163,12 +168,15 @@ private:
bool accept();
+ void clearProcessCreationThread();
+
LLSocket::ptr_t mListenSocket;
LLSocket::ptr_t mSocket;
U32 mBoundPort;
LLProcess::Params mProcessParams;
LLProcessPtr mProcess;
+ LLThread *pProcessCreationThread;
std::string mPluginFile;
std::string mPluginDir;