diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp
index 1b0e03cb2a85c1afaa839229119766a13c5ca3d9..411977474b5e4ab26976531e56ee08449d6f2c99 100644
--- a/indra/llcommon/llworkerthread.cpp
+++ b/indra/llcommon/llworkerthread.cpp
@@ -65,6 +65,27 @@ LLWorkerThread::~LLWorkerThread()
 	// ~LLQueuedThread() will be called here
 }
 
+//called only in destructor.
+void LLWorkerThread::clearDeleteList()
+{
+	// Delete any workers in the delete queue (should be safe - had better be!)
+	if (!mDeleteList.empty())
+	{
+		llwarns << "Worker Thread: " << mName << " destroyed with " << mDeleteList.size()
+				<< " entries in delete list." << llendl;
+
+		mDeleteMutex->lock();
+		for (delete_list_t::iterator iter = mDeleteList.begin(); iter != mDeleteList.end(); ++iter)
+		{
+			(*iter)->mRequestHandle = LLWorkerThread::nullHandle();
+			(*iter)->clearFlags(LLWorkerClass::WCF_HAVE_WORK);
+			delete *iter ;
+		}
+		mDeleteList.clear() ;
+		mDeleteMutex->unlock() ;
+	}
+}
+
 // virtual
 S32 LLWorkerThread::update(U32 max_time_ms)
 {
@@ -320,7 +341,20 @@ bool LLWorkerClass::checkWork(bool aborting)
 	if (mRequestHandle != LLWorkerThread::nullHandle())
 	{
 		LLWorkerThread::WorkRequest* workreq = (LLWorkerThread::WorkRequest*)mWorkerThread->getRequest(mRequestHandle);
-		llassert_always(workreq);
+		if(!workreq)
+		{
+			if(mWorkerThread->isQuitting() || mWorkerThread->isStopped()) //the mWorkerThread is not running
+			{
+				mRequestHandle = LLWorkerThread::nullHandle();
+				clearFlags(WCF_HAVE_WORK);
+				return true ;
+			}
+			else
+			{
+				llassert_always(workreq);
+			}
+		}
+
 		LLQueuedThread::status_t status = workreq->getStatus();
 		if (status == LLWorkerThread::STATUS_ABORTED)
 		{
diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h
index a1e85d2ecc871143ea38c60e68ff32c9ec3def85..1756ebab6b79333dbf0da490cfd9c0c0e42be944 100644
--- a/indra/llcommon/llworkerthread.h
+++ b/indra/llcommon/llworkerthread.h
@@ -80,6 +80,9 @@ class LL_COMMON_API LLWorkerThread : public LLQueuedThread
 		S32 mParam;
 	};
 
+protected:
+	void clearDeleteList() ;
+
 private:
 	typedef std::list<LLWorkerClass*> delete_list_t;
 	delete_list_t mDeleteList;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 948d38befb7d4c89e4fa876948c19b663386aac2..d7b605fb08972cb5531d5913a75cbf166c0a2794 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1515,7 +1515,7 @@ bool LLAppViewer::cleanup()
 	LLAvatarIconIDCache::getInstance()->save();
 
 	llinfos << "Shutting down Threads" << llendflush;
-	
+
 	// Let threads finish
 	LLTimer idleTimer;
 	idleTimer.reset();
@@ -1529,19 +1529,26 @@ bool LLAppViewer::cleanup()
 		pending += LLVFSThread::updateClass(0);
 		pending += LLLFSThread::updateClass(0);
 		F64 idle_time = idleTimer.getElapsedTimeF64();
-		if (!pending || idle_time >= max_idle_time)
+		if(!pending)
+		{
+			break ; //done
+		}
+		else if(idle_time >= max_idle_time)
 		{
 			llwarns << "Quitting with pending background tasks." << llendl;
 			break;
 		}
 	}
-	
+
 	// Delete workers first
 	// shotdown all worker threads before deleting them in case of co-dependencies
 	sTextureCache->shutdown();
 	sTextureFetch->shutdown();
 	sImageDecodeThread->shutdown();
 	
+	sTextureFetch->shutDownTextureCacheThread() ;
+	sTextureFetch->shutDownImageDecodeThread() ;
+
 	delete sTextureCache;
     sTextureCache = NULL;
 	delete sTextureFetch;
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index 91c303c79e7c308cb884209b09d942a66e93e1c8..3116c8feb0cf3c6df5113fa5bb0aa2583a019a69 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -750,6 +750,7 @@ LLTextureCache::LLTextureCache(bool threaded)
 
 LLTextureCache::~LLTextureCache()
 {
+	clearDeleteList() ;
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -1574,6 +1575,11 @@ bool LLTextureCache::readComplete(handle_t handle, bool abort)
 	{
 		worker = iter->second;
 		complete = worker->complete();
+
+		if(!complete && abort)
+		{
+			abortRequest(handle, true) ;
+		}
 	}
 	if (worker && (complete || abort))
 	{
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 0053ce8df8e6e42d68caf1f2133e8e68535a73c1..b1b3ae473cf6740c63ae7edfe016317089f09233 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -431,11 +431,11 @@ LLTextureFetchWorker::~LLTextureFetchWorker()
 // 			<< " Desired=" << mDesiredDiscard << llendl;
 	llassert_always(!haveWork());
 	lockWorkMutex();
-	if (mCacheReadHandle != LLTextureCache::nullHandle())
+	if (mCacheReadHandle != LLTextureCache::nullHandle() && mFetcher->mTextureCache)
 	{
 		mFetcher->mTextureCache->readComplete(mCacheReadHandle, true);
 	}
-	if (mCacheWriteHandle != LLTextureCache::nullHandle())
+	if (mCacheWriteHandle != LLTextureCache::nullHandle() && mFetcher->mTextureCache)
 	{
 		mFetcher->mTextureCache->writeComplete(mCacheWriteHandle, true);
 	}
@@ -1429,6 +1429,8 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
 
 LLTextureFetch::~LLTextureFetch()
 {
+	clearDeleteList() ;
+
 	// ~LLQueuedThread() called here
 }
 
@@ -1737,6 +1739,26 @@ S32 LLTextureFetch::update(U32 max_time_ms)
 	return res;
 }
 
+//called in the MAIN thread after the TextureCacheThread shuts down.
+void LLTextureFetch::shutDownTextureCacheThread() 
+{
+	if(mTextureCache)
+	{
+		llassert_always(mTextureCache->isQuitting() || mTextureCache->isStopped()) ;
+		mTextureCache = NULL ;
+	}
+}
+	
+//called in the MAIN thread after the ImageDecodeThread shuts down.
+void LLTextureFetch::shutDownImageDecodeThread() 
+{
+	if(mImageDecodeThread)
+	{
+		llassert_always(mImageDecodeThread->isQuitting() || mImageDecodeThread->isStopped()) ;
+		mImageDecodeThread = NULL ;
+	}
+}
+
 // WORKER THREAD
 void LLTextureFetch::startThread()
 {
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index 5213c4f4883d1d5d4df1bc14394ef5962d51ee05..ef2ec520bfd7639861c201324e112af71162763e 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -58,6 +58,8 @@ class LLTextureFetch : public LLWorkerThread
 	~LLTextureFetch();
 
 	/*virtual*/ S32 update(U32 max_time_ms);	
+	void shutDownTextureCacheThread() ; //called in the main thread after the TextureCacheThread shuts down.
+	void shutDownImageDecodeThread() ;  //called in the main thread after the ImageDecodeThread shuts down.
 
 	bool createRequest(const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,
 					   S32 w, S32 h, S32 c, S32 discard, bool needs_aux);