SH-4645 Viewer hangs on exit after cancelling a mesh upload.

Fri, 06 Dec 2013 16:02:53 -0500

author
Monty Brandenberg <monty@lindenlab.com>
date
Fri, 06 Dec 2013 16:02:53 -0500
changeset 40739
805055e04c78
parent 40738
f0b6756e6e0b
child 40740
ba1f758296e6

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.

indra/newview/llmeshrepository.cpp file | annotate | diff | revisions
indra/newview/llmeshrepository.h file | annotate | diff | revisions
     1.1 --- a/indra/newview/llmeshrepository.cpp	Thu Dec 05 15:26:38 2013 -0500
     1.2 +++ b/indra/newview/llmeshrepository.cpp	Fri Dec 06 16:02:53 2013 -0500
     1.3 @@ -257,6 +257,11 @@
     1.4  //     mGetMeshVersion          mMutex        rw.main.mMutex, ro.repo.mMutex
     1.5  //     mHttp*                   none          rw.repo.none
     1.6  //
     1.7 +//   LLMeshUploadThread:
     1.8 +//
     1.9 +//     mDiscarded               mMutex        rw.main.mMutex, ro.uploadN.none [1]
    1.10 +//     ... more ...
    1.11 +//
    1.12  // QA/Development Testing
    1.13  //
    1.14  //   Debug variable 'MeshUploadFakeErrors' takes a mask of bits that will
    1.15 @@ -1852,7 +1857,7 @@
    1.16  									   LLHandle<LLWholeModelUploadObserver> upload_observer)
    1.17    : LLThread("mesh upload"),
    1.18  	LLCore::HttpHandler(),
    1.19 -	mDiscarded(FALSE),
    1.20 +	mDiscarded(false),
    1.21  	mDoUpload(do_upload),
    1.22  	mWholeModelUploadURL(upload_url),
    1.23  	mFeeObserverHandle(fee_observer),
    1.24 @@ -1940,10 +1945,10 @@
    1.25  void LLMeshUploadThread::discard()
    1.26  {
    1.27  	LLMutexLock lock(mMutex);
    1.28 -	mDiscarded = TRUE;
    1.29 +	mDiscarded = true;
    1.30  }
    1.31  
    1.32 -BOOL LLMeshUploadThread::isDiscarded() const
    1.33 +bool LLMeshUploadThread::isDiscarded() const
    1.34  {
    1.35  	LLMutexLock lock(mMutex);
    1.36  	return mDiscarded;
    1.37 @@ -2199,7 +2204,13 @@
    1.38  		
    1.39  	if (has_valid_requests)
    1.40  	{
    1.41 -		while (!mPhysicsComplete)
    1.42 +		// *NOTE:  Interesting livelock condition on shutdown.  If there
    1.43 +		// is an upload request in generateHulls() when shutdown starts,
    1.44 +		// the main thread isn't available to manage communication between
    1.45 +		// the decomposition thread and the upload thread and this loop
    1.46 +		// wouldn't complete in turn stalling the main thread.  The check
    1.47 +		// on isDiscarded() prevents that.
    1.48 +		while (! mPhysicsComplete && ! isDiscarded())
    1.49  		{
    1.50  			apr_sleep(100);
    1.51  		}
    1.52 @@ -2253,13 +2264,21 @@
    1.53  			LL_DEBUGS(LOG_MESH) << "POST request issued." << LL_ENDL;
    1.54  			
    1.55  			mHttpRequest->update(0);
    1.56 -			while (! LLApp::isQuitting() && ! mFinished)
    1.57 +			while (! LLApp::isQuitting() && ! finished() && ! isDiscarded())
    1.58  			{
    1.59  				ms_sleep(sleep_time);
    1.60  				sleep_time = llmin(250U, sleep_time + sleep_time);
    1.61  				mHttpRequest->update(0);
    1.62  			}
    1.63 -			LL_DEBUGS(LOG_MESH) << "Mesh upload operation completed." << LL_ENDL;
    1.64 +
    1.65 +			if (isDiscarded())
    1.66 +			{
    1.67 +				LL_DEBUGS(LOG_MESH) << "Mesh upload operation discarded." << LL_ENDL;
    1.68 +			}
    1.69 +			else
    1.70 +			{
    1.71 +				LL_DEBUGS(LOG_MESH) << "Mesh upload operation completed." << LL_ENDL;
    1.72 +			}
    1.73  		}
    1.74  	}
    1.75  }
    1.76 @@ -2299,12 +2318,16 @@
    1.77  		U32 sleep_time(10);
    1.78  		
    1.79  		mHttpRequest->update(0);
    1.80 -		while (! LLApp::isQuitting() && ! mFinished)
    1.81 +		while (! LLApp::isQuitting() && ! finished() && ! isDiscarded())
    1.82  		{
    1.83  			ms_sleep(sleep_time);
    1.84  			sleep_time = llmin(250U, sleep_time + sleep_time);
    1.85  			mHttpRequest->update(0);
    1.86  		}
    1.87 +		if (isDiscarded())
    1.88 +		{
    1.89 +			LL_DEBUGS(LOG_MESH) << "Mesh fee query operation discarded." << LL_ENDL;
    1.90 +		}
    1.91  	}
    1.92  }
    1.93  
    1.94 @@ -3020,7 +3043,7 @@
    1.95  
    1.96  	for (U32 i = 0; i < mUploads.size(); ++i)
    1.97  	{
    1.98 -		LL_INFOS(LOG_MESH) << "Waiting for pending mesh upload " << i << "/" << mUploads.size() << LL_ENDL;
    1.99 +		LL_INFOS(LOG_MESH) << "Waiting for pending mesh upload " << (i + 1) << "/" << mUploads.size() << LL_ENDL;
   1.100  		while (!mUploads[i]->isStopped())
   1.101  		{
   1.102  			apr_sleep(10);
     2.1 --- a/indra/newview/llmeshrepository.h	Thu Dec 05 15:26:38 2013 -0500
     2.2 +++ b/indra/newview/llmeshrepository.h	Fri Dec 06 16:02:53 2013 -0500
     2.3 @@ -447,7 +447,7 @@
     2.4  	bool			mUploadTextures;
     2.5  	bool			mUploadSkin;
     2.6  	bool			mUploadJoints;
     2.7 -	BOOL            mDiscarded;
     2.8 +	volatile bool	mDiscarded;
     2.9  
    2.10  	LLHost			mHost;
    2.11  	std::string		mWholeModelFeeCapability;
    2.12 @@ -463,7 +463,7 @@
    2.13  	virtual void run();
    2.14  	void preStart();
    2.15  	void discard() ;
    2.16 -	BOOL isDiscarded() const;
    2.17 +	bool isDiscarded() const;
    2.18  
    2.19  	void generateHulls();
    2.20  

mercurial