diff options
author | Monty Brandenberg <monty@lindenlab.com> | 2013-12-06 16:02:53 -0500 |
---|---|---|
committer | Monty Brandenberg <monty@lindenlab.com> | 2013-12-06 16:02:53 -0500 |
commit | ea1f6a6343fe83f1352a8a839265c471640acdce (patch) | |
tree | 191405e3370bb870b7ec527503d562d2040f72b5 /indra/newview/llmeshrepository.cpp | |
parent | da135de77dea24427f5e658ebac43b77c215cc9b (diff) |
SH-4645 Viewer hangs on exit after cancelling a mesh upload.
Problem involved a 3-way livelock between the main, upload
and decomposition threads. Viewer is shutting down but an
upload is in the 'generate hulls' state. Main thread asks
upload request to discard and spins waiting for it to finish.
Upload thread is in generateHulls spinning waiting for the
decomposition thread to process a mesh request. Decomposition
thread is sleeping waiting for main thread to deliver work
that upload thread has asked the decomposition thread to do.
Diffstat (limited to 'indra/newview/llmeshrepository.cpp')
-rwxr-xr-x | indra/newview/llmeshrepository.cpp | 39 |
1 files changed, 31 insertions, 8 deletions
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index ebfb22a360..4296abb2cc 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -257,6 +257,11 @@ // mGetMeshVersion mMutex rw.main.mMutex, ro.repo.mMutex // mHttp* none rw.repo.none // +// LLMeshUploadThread: +// +// mDiscarded mMutex rw.main.mMutex, ro.uploadN.none [1] +// ... more ... +// // QA/Development Testing // // Debug variable 'MeshUploadFakeErrors' takes a mask of bits that will @@ -1852,7 +1857,7 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data, LLHandle<LLWholeModelUploadObserver> upload_observer) : LLThread("mesh upload"), LLCore::HttpHandler(), - mDiscarded(FALSE), + mDiscarded(false), mDoUpload(do_upload), mWholeModelUploadURL(upload_url), mFeeObserverHandle(fee_observer), @@ -1940,10 +1945,10 @@ void LLMeshUploadThread::preStart() void LLMeshUploadThread::discard() { LLMutexLock lock(mMutex); - mDiscarded = TRUE; + mDiscarded = true; } -BOOL LLMeshUploadThread::isDiscarded() const +bool LLMeshUploadThread::isDiscarded() const { LLMutexLock lock(mMutex); return mDiscarded; @@ -2199,7 +2204,13 @@ void LLMeshUploadThread::generateHulls() if (has_valid_requests) { - while (!mPhysicsComplete) + // *NOTE: Interesting livelock condition on shutdown. If there + // is an upload request in generateHulls() when shutdown starts, + // the main thread isn't available to manage communication between + // the decomposition thread and the upload thread and this loop + // wouldn't complete in turn stalling the main thread. The check + // on isDiscarded() prevents that. + while (! mPhysicsComplete && ! isDiscarded()) { apr_sleep(100); } @@ -2253,13 +2264,21 @@ void LLMeshUploadThread::doWholeModelUpload() LL_DEBUGS(LOG_MESH) << "POST request issued." << LL_ENDL; mHttpRequest->update(0); - while (! LLApp::isQuitting() && ! mFinished) + while (! LLApp::isQuitting() && ! finished() && ! isDiscarded()) { ms_sleep(sleep_time); sleep_time = llmin(250U, sleep_time + sleep_time); mHttpRequest->update(0); } - LL_DEBUGS(LOG_MESH) << "Mesh upload operation completed." << LL_ENDL; + + if (isDiscarded()) + { + LL_DEBUGS(LOG_MESH) << "Mesh upload operation discarded." << LL_ENDL; + } + else + { + LL_DEBUGS(LOG_MESH) << "Mesh upload operation completed." << LL_ENDL; + } } } } @@ -2299,12 +2318,16 @@ void LLMeshUploadThread::requestWholeModelFee() U32 sleep_time(10); mHttpRequest->update(0); - while (! LLApp::isQuitting() && ! mFinished) + while (! LLApp::isQuitting() && ! finished() && ! isDiscarded()) { ms_sleep(sleep_time); sleep_time = llmin(250U, sleep_time + sleep_time); mHttpRequest->update(0); } + if (isDiscarded()) + { + LL_DEBUGS(LOG_MESH) << "Mesh fee query operation discarded." << LL_ENDL; + } } } @@ -3020,7 +3043,7 @@ void LLMeshRepository::shutdown() for (U32 i = 0; i < mUploads.size(); ++i) { - LL_INFOS(LOG_MESH) << "Waiting for pending mesh upload " << i << "/" << mUploads.size() << LL_ENDL; + LL_INFOS(LOG_MESH) << "Waiting for pending mesh upload " << (i + 1) << "/" << mUploads.size() << LL_ENDL; while (!mUploads[i]->isStopped()) { apr_sleep(10); |