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

@@ -72,7 +72,8 @@ public:
enum flags_t {
FLAG_AUTO_COMPLETE = 1,
FLAG_AUTO_DELETE = 2, // child-class dependent
FLAG_ABORT = 4
FLAG_ABORT = 4,
FLAG_LOCKED = 8
};
typedef U32 handle_t;
@@ -122,6 +123,10 @@ public:
// NOTE: flags are |'d
mFlags |= flags;
}
void resetFlags(U32 flags)
{
mFlags &= ~flags;
}
virtual bool processRequest() = 0; // Return true when request has completed
virtual void finishRequest(bool completed); // Always called from thread after request has completed or aborted