Skip to content
Snippets Groups Projects
Commit 77b13dc2 authored by Monroe Linden's avatar Monroe Linden
Browse files

Incorporate suggestions from Richard's review of the LLPlugin changes.

Use LLMutexLock (stack-based locker/unlocker) for the straightforward cases instead of explicit lock()/unlock().

There are still a couple of cases (one overlapping lock lifetime and two loops that unlock the mutex to call another function inside the loop) where I'm leaving explicit lock/unlock calls.

Rename LLPluginProcessParent::sPollThread to sReadThread, for consistency.

Made the LLPluginProcessParent destructor hold mIncomingQueueMutex while removing the instance from the global list -- this should prevent a possible race condition in LLPluginProcessParent::poll().

Removed a redundant check when calling LLPluginProcessParent::setUseReadThread().
parent dacc5afb
Branches
Tags
No related merge requests found
...@@ -117,10 +117,9 @@ LLPluginMessagePipe::~LLPluginMessagePipe() ...@@ -117,10 +117,9 @@ LLPluginMessagePipe::~LLPluginMessagePipe()
bool LLPluginMessagePipe::addMessage(const std::string &message) bool LLPluginMessagePipe::addMessage(const std::string &message)
{ {
// queue the message for later output // queue the message for later output
mOutputMutex.lock(); LLMutexLock lock(&mOutputMutex);
mOutput += message; mOutput += message;
mOutput += MESSAGE_DELIMITER; // message separator mOutput += MESSAGE_DELIMITER; // message separator
mOutputMutex.unlock();
return true; return true;
} }
...@@ -173,7 +172,7 @@ bool LLPluginMessagePipe::pumpOutput() ...@@ -173,7 +172,7 @@ bool LLPluginMessagePipe::pumpOutput()
apr_status_t status; apr_status_t status;
apr_size_t size; apr_size_t size;
mOutputMutex.lock(); LLMutexLock lock(&mOutputMutex);
if(!mOutput.empty()) if(!mOutput.empty())
{ {
// write any outgoing messages // write any outgoing messages
...@@ -225,7 +224,6 @@ bool LLPluginMessagePipe::pumpOutput() ...@@ -225,7 +224,6 @@ bool LLPluginMessagePipe::pumpOutput()
result = false; result = false;
} }
} }
mOutputMutex.unlock();
} }
return result; return result;
...@@ -288,9 +286,8 @@ bool LLPluginMessagePipe::pumpInput(F64 timeout) ...@@ -288,9 +286,8 @@ bool LLPluginMessagePipe::pumpInput(F64 timeout)
if(size > 0) if(size > 0)
{ {
mInputMutex.lock(); LLMutexLock lock(&mInputMutex);
mInput.append(input_buf, size); mInput.append(input_buf, size);
mInputMutex.unlock();
} }
if(status == APR_SUCCESS) if(status == APR_SUCCESS)
......
...@@ -50,7 +50,7 @@ apr_pollset_t *LLPluginProcessParent::sPollSet = NULL; ...@@ -50,7 +50,7 @@ apr_pollset_t *LLPluginProcessParent::sPollSet = NULL;
bool LLPluginProcessParent::sPollsetNeedsRebuild = false; bool LLPluginProcessParent::sPollsetNeedsRebuild = false;
LLMutex *LLPluginProcessParent::sInstancesMutex; LLMutex *LLPluginProcessParent::sInstancesMutex;
std::list<LLPluginProcessParent*> LLPluginProcessParent::sInstances; std::list<LLPluginProcessParent*> LLPluginProcessParent::sInstances;
LLThread *LLPluginProcessParent::sPollThread = NULL; LLThread *LLPluginProcessParent::sReadThread = NULL;
class LLPluginProcessParentPollThread: public LLThread class LLPluginProcessParentPollThread: public LLThread
...@@ -108,9 +108,10 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner): ...@@ -108,9 +108,10 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner):
mHeartbeat.stop(); mHeartbeat.stop();
// Don't add to the global list until fully constructed. // Don't add to the global list until fully constructed.
sInstancesMutex->lock(); {
LLMutexLock lock(sInstancesMutex);
sInstances.push_back(this); sInstances.push_back(this);
sInstancesMutex->unlock(); }
} }
LLPluginProcessParent::~LLPluginProcessParent() LLPluginProcessParent::~LLPluginProcessParent()
...@@ -118,9 +119,14 @@ LLPluginProcessParent::~LLPluginProcessParent() ...@@ -118,9 +119,14 @@ LLPluginProcessParent::~LLPluginProcessParent()
LL_DEBUGS("Plugin") << "destructor" << LL_ENDL; LL_DEBUGS("Plugin") << "destructor" << LL_ENDL;
// Remove from the global list before beginning destruction. // Remove from the global list before beginning destruction.
sInstancesMutex->lock(); {
// Make sure to get the global mutex _first_ here, to avoid a possible deadlock against LLPluginProcessParent::poll()
LLMutexLock lock(sInstancesMutex);
{
LLMutexLock lock2(&mIncomingQueueMutex);
sInstances.remove(this); sInstances.remove(this);
sInstancesMutex->unlock(); }
}
// Destroy any remaining shared memory regions // Destroy any remaining shared memory regions
sharedMemoryRegionsType::iterator iter; sharedMemoryRegionsType::iterator iter;
...@@ -139,9 +145,11 @@ LLPluginProcessParent::~LLPluginProcessParent() ...@@ -139,9 +145,11 @@ LLPluginProcessParent::~LLPluginProcessParent()
void LLPluginProcessParent::killSockets(void) void LLPluginProcessParent::killSockets(void)
{ {
mIncomingQueueMutex.lock(); {
LLMutexLock lock(&mIncomingQueueMutex);
killMessagePipe(); killMessagePipe();
mIncomingQueueMutex.unlock(); }
mListenSocket.reset(); mListenSocket.reset();
mSocket.reset(); mSocket.reset();
} }
...@@ -619,10 +627,10 @@ void LLPluginProcessParent::dirtyPollSet() ...@@ -619,10 +627,10 @@ void LLPluginProcessParent::dirtyPollSet()
{ {
sPollsetNeedsRebuild = true; sPollsetNeedsRebuild = true;
if(sPollThread) if(sReadThread)
{ {
LL_DEBUGS("PluginPoll") << "unpausing polling thread " << LL_ENDL; LL_DEBUGS("PluginPoll") << "unpausing read thread " << LL_ENDL;
sPollThread->unpause(); sReadThread->unpause();
} }
} }
...@@ -634,7 +642,7 @@ void LLPluginProcessParent::updatePollset() ...@@ -634,7 +642,7 @@ void LLPluginProcessParent::updatePollset()
return; return;
} }
sInstancesMutex->lock(); LLMutexLock lock(sInstancesMutex);
if(sPollSet) if(sPollSet)
{ {
...@@ -658,7 +666,7 @@ void LLPluginProcessParent::updatePollset() ...@@ -658,7 +666,7 @@ void LLPluginProcessParent::updatePollset()
} }
} }
if(sUseReadThread && sPollThread && !sPollThread->isQuitting()) if(sUseReadThread && sReadThread && !sReadThread->isQuitting())
{ {
if(!sPollSet && (count > 0)) if(!sPollSet && (count > 0))
{ {
...@@ -692,7 +700,6 @@ void LLPluginProcessParent::updatePollset() ...@@ -692,7 +700,6 @@ void LLPluginProcessParent::updatePollset()
} }
} }
} }
sInstancesMutex->unlock();
} }
void LLPluginProcessParent::setUseReadThread(bool use_read_thread) void LLPluginProcessParent::setUseReadThread(bool use_read_thread)
...@@ -703,26 +710,26 @@ void LLPluginProcessParent::setUseReadThread(bool use_read_thread) ...@@ -703,26 +710,26 @@ void LLPluginProcessParent::setUseReadThread(bool use_read_thread)
if(sUseReadThread) if(sUseReadThread)
{ {
if(!sPollThread) if(!sReadThread)
{ {
// start up the read thread // start up the read thread
LL_INFOS("PluginPoll") << "creating polling thread " << LL_ENDL; LL_INFOS("PluginPoll") << "creating read thread " << LL_ENDL;
// make sure the pollset gets rebuilt. // make sure the pollset gets rebuilt.
sPollsetNeedsRebuild = true; sPollsetNeedsRebuild = true;
sPollThread = new LLPluginProcessParentPollThread; sReadThread = new LLPluginProcessParentPollThread;
sPollThread->start(); sReadThread->start();
} }
} }
else else
{ {
if(sPollThread) if(sReadThread)
{ {
// shut down the read thread // shut down the read thread
LL_INFOS("PluginPoll") << "destroying polling thread " << LL_ENDL; LL_INFOS("PluginPoll") << "destroying read thread " << LL_ENDL;
delete sPollThread; delete sReadThread;
sPollThread = NULL; sReadThread = NULL;
} }
} }
...@@ -756,8 +763,9 @@ void LLPluginProcessParent::poll(F64 timeout) ...@@ -756,8 +763,9 @@ void LLPluginProcessParent::poll(F64 timeout)
if(self) if(self)
{ {
// Make sure this pointer is still in the instances list // Make sure this pointer is still in the instances list
sInstancesMutex->lock();
bool valid = false; bool valid = false;
{
LLMutexLock lock(sInstancesMutex);
for(std::list<LLPluginProcessParent*>::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) for(std::list<LLPluginProcessParent*>::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter)
{ {
if(*iter == self) if(*iter == self)
...@@ -769,7 +777,7 @@ void LLPluginProcessParent::poll(F64 timeout) ...@@ -769,7 +777,7 @@ void LLPluginProcessParent::poll(F64 timeout)
break; break;
} }
} }
sInstancesMutex->unlock(); }
if(valid) if(valid)
{ {
...@@ -872,9 +880,7 @@ void LLPluginProcessParent::receiveMessageEarly(const LLPluginMessage &message) ...@@ -872,9 +880,7 @@ void LLPluginProcessParent::receiveMessageEarly(const LLPluginMessage &message)
if(!handled) if(!handled)
{ {
// any message that wasn't handled early needs to be queued. // any message that wasn't handled early needs to be queued.
// mIncomingQueueMutex.lock();
mIncomingQueue.push(message); mIncomingQueue.push(message);
// mIncomingQueueMutex.unlock();
} }
} }
......
...@@ -188,7 +188,7 @@ class LLPluginProcessParent : public LLPluginMessagePipeOwner ...@@ -188,7 +188,7 @@ class LLPluginProcessParent : public LLPluginMessagePipeOwner
static void dirtyPollSet(); static void dirtyPollSet();
static void updatePollset(); static void updatePollset();
void servicePoll(); void servicePoll();
static LLThread *sPollThread; static LLThread *sReadThread;
LLMutex mIncomingQueueMutex; LLMutex mIncomingQueueMutex;
std::queue<LLPluginMessage> mIncomingQueue; std::queue<LLPluginMessage> mIncomingQueue;
......
...@@ -740,12 +740,8 @@ void LLViewerMedia::updateMedia(void *dummy_arg) ...@@ -740,12 +740,8 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
{ {
LLFastTimer t1(FTM_MEDIA_UPDATE); LLFastTimer t1(FTM_MEDIA_UPDATE);
bool use_read_thread = gSavedSettings.getBOOL("PluginUseReadThread");
if(LLPluginProcessParent::getUseReadThread() != use_read_thread)
{
// Enable/disable the plugin read thread // Enable/disable the plugin read thread
LLPluginProcessParent::setUseReadThread(use_read_thread); LLPluginProcessParent::setUseReadThread(gSavedSettings.getBOOL("PluginUseReadThread"));
}
sAnyMediaShowing = false; sAnyMediaShowing = false;
sUpdatedCookies = getCookieStore()->getChangedCookies(); sUpdatedCookies = getCookieStore()->getChangedCookies();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment