Avoid dead lock in LLQueuedThread::generateHandle / LLTextureFetchWorker::callbackDecoded

Thead 1:

indra/llcommon/llqueuedthread.cpp:456:

452                     if (complete)
453                     {
454                             lockData();             // This locks LLThread::mRunCondition
455                             req->setStatus(STATUS_COMPLETE);
456                             req->finishRequest(true);

LLImageDecodeThread::ImageRequest::finishRequest calls:
    mResponder->completed(success, mDecodedImageRaw, mDecodedImageAux);

LLTextureFetchWorker::DecodeResponder::completed calls:
    worker->callbackDecoded(success, raw, aux);

LLTextureFetchWorker::callbackDecoded calls:
    LLMutexLock lock(&mWorkMutex);                      // This locks LLTextureFetchWorker::mWorkMutex

Thread 2:

LLTextureFetchWorker::doWork calls:
    LLMutexLock lock(&mWorkMutex);                      // This locks LLTextureFetchWorker::mWorkMutex
    .
    .
    .
    mDecodeHandle = mFetcher->mImageDecodeThread->decodeImage(mFormattedImage, image_priority, discard, mNeedsAux, new DecodeResponder(mFetcher, mID, this));

LLImageDecodeThread::decodeImage calls:
    handle_t handle = generateHandle();

LLQueuedThread::generateHandle calls:
    lockData();                                         // This locks LLThread::mRunCondition
This commit is contained in:
Aleric Inglewood
2012-07-22 04:13:23 +02:00
parent 891a330955
commit 2830b35aa6
4 changed files with 74 additions and 23 deletions

View File

@@ -226,7 +226,8 @@ LLWorkerClass::~LLWorkerClass()
llerrs << "LLWorkerClass destroyed with stale work handle" << llendl;
}
if (workreq->getStatus() != LLWorkerThread::STATUS_ABORTED &&
workreq->getStatus() != LLWorkerThread::STATUS_COMPLETE)
workreq->getStatus() != LLWorkerThread::STATUS_COMPLETE &&
!(workreq->getFlags() & LLWorkerThread::FLAG_LOCKED))
{
llerrs << "LLWorkerClass destroyed with active worker! Worker Status: " << workreq->getStatus() << llendl;
}
@@ -350,14 +351,10 @@ bool LLWorkerClass::checkWork(bool aborting)
}
LLQueuedThread::status_t status = workreq->getStatus();
if (status == LLWorkerThread::STATUS_ABORTED)
if (status == LLWorkerThread::STATUS_COMPLETE || status == LLWorkerThread::STATUS_ABORTED)
{
complete = true;
abort = true;
}
else if (status == LLWorkerThread::STATUS_COMPLETE)
{
complete = true;
complete = !(workreq->getFlags() & LLWorkerThread::FLAG_LOCKED);
abort = status == LLWorkerThread::STATUS_ABORTED;
}
else
{