diff options
author | Andrey Lihatskiy <alihatskiy@productengine.com> | 2022-02-28 21:56:25 +0200 |
---|---|---|
committer | Andrey Lihatskiy <alihatskiy@productengine.com> | 2022-02-28 21:56:25 +0200 |
commit | 1e0eafd50cc03f0796fe8678d3460aac614db603 (patch) | |
tree | 6b9efda5d63749238a786667fc2ac4c9b3fabfad /indra/llplugin | |
parent | 1f1d762693027a0f6ce7b913bcc8984767e947be (diff) | |
parent | 6ca09a94554ec01f5c94ec60fffd01d7e33f3546 (diff) |
Merge branch 'master' into DRTVWR-544-maint
# Conflicts:
# indra/llaudio/llstreamingaudio_fmodstudio.cpp
# indra/newview/llviewerregion.cpp
Diffstat (limited to 'indra/llplugin')
-rw-r--r-- | indra/llplugin/llpluginprocessparent.cpp | 122 | ||||
-rw-r--r-- | indra/llplugin/llpluginprocessparent.h | 8 |
2 files changed, 117 insertions, 13 deletions
diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp index e50db69190..eef22156bc 100644 --- a/indra/llplugin/llpluginprocessparent.cpp +++ b/indra/llplugin/llpluginprocessparent.cpp @@ -80,8 +80,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) { @@ -110,6 +131,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; @@ -160,6 +193,7 @@ void LLPluginProcessParent::shutdown() && state != STATE_ERROR) { (*it).second->setState(STATE_GOODBYE); + (*it).second->mOwner = NULL; } if (state != STATE_DONE) { @@ -314,6 +348,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; @@ -321,8 +384,9 @@ void LLPluginProcessParent::idle(void) do { // process queued messages - mIncomingQueueMutex.lock(); - while(!mIncomingQueue.empty()) + // Inside main thread, it is preferable not to block it on mutex. + bool locked = mIncomingQueueMutex.trylock(); + while(locked && !mIncomingQueue.empty()) { LLPluginMessage message = mIncomingQueue.front(); mIncomingQueue.pop(); @@ -330,10 +394,13 @@ void LLPluginProcessParent::idle(void) receiveMessage(message); - mIncomingQueueMutex.lock(); + locked = mIncomingQueueMutex.trylock(); } - mIncomingQueueMutex.unlock(); + if (locked) + { + mIncomingQueueMutex.unlock(); + } // Give time to network processing if(mMessagePipe) @@ -342,7 +409,10 @@ void LLPluginProcessParent::idle(void) mMessagePipe->pumpOutput(); // Only do input processing here if this instance isn't in a pollset. - if(!mPolledInput) + // If viewer and plugin are both shutting down, don't process further + // input, viewer won't be able to handle it. + if(!mPolledInput + && !(mState >= STATE_GOODBYE && LLApp::isExiting())) { mMessagePipe->pumpInput(); } @@ -469,14 +539,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) { @@ -505,6 +591,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); } } @@ -607,6 +702,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; |