From e6025de0d03749c9d89c33da76aa8952ab6119d1 Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Tue, 31 Jan 2023 15:04:17 -0500
Subject: [PATCH] Small overhaul of LLThread for better shutdown behavior

---
 indra/llcommon/llthread.cpp        | 43 ++++++++++++++----------------
 indra/llcommon/llthread.h          | 15 +++++------
 indra/newview/llmeshrepository.cpp | 10 +++----
 3 files changed, 31 insertions(+), 37 deletions(-)

diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 6aa6dc8335c..5934961b79a 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -124,19 +124,18 @@ LL_COMMON_API void assert_main_thread()
 }
 
 //
-// Handed to the APR thread creation function
+// Handed to the thread creation function
 //
 void LLThread::threadRun()
 {
+    // Set thread state to running
+    mStatus = RUNNING;
+
 #ifdef LL_WINDOWS
     set_thread_name(mName.c_str());
 #endif
-
     LL_PROFILER_SET_THREAD_NAME( mName.c_str() );
 
-    // this is the first point at which we're actually running in the new thread
-    mID = currentID();
-
 #ifndef LL_RELEASE_FOR_DOWNLOAD
     // for now, hard code all LLThreads to report to single master thread recorder, which is known to be running on main thread
     mRecorder = new LLTrace::ThreadRecorder(*LLTrace::get_master_thread_recorder());
@@ -182,14 +181,13 @@ void LLThread::threadRun()
 LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
     mPaused(FALSE),
     mName(name),
-    mThreadp(NULL),
     mStatus(STOPPED)
 #ifndef LL_RELEASE_FOR_DOWNLOAD
     , mRecorder(NULL)
 #endif
 {
-    mRunCondition = new LLCondition();
-    mDataLock = new LLMutex();
+    mRunCondition = std::make_unique<LLCondition>();
+    mDataLock = std::make_unique<LLMutex>();
     mLocalAPRFilePoolp = NULL ;
 }
 
@@ -251,16 +249,11 @@ void LLThread::shutdown()
             mThreadp->join();
             LL_INFOS() << "Successfully joined thread: " << mName << LL_ENDL;
         }
-
-        delete mThreadp;
-        mThreadp = NULL;
     }
 
-    delete mRunCondition;
-    mRunCondition = NULL;
-
-    delete mDataLock;
-    mDataLock = NULL;
+    mThreadp.reset();
+    mRunCondition.reset();
+    mDataLock.reset();
 #ifndef LL_RELEASE_FOR_DOWNLOAD
     if (mRecorder)
     {
@@ -272,24 +265,28 @@ void LLThread::shutdown()
 #endif
 }
 
-
 void LLThread::start()
 {
     llassert(isStopped());
-    
-    // Set thread state to running
-    mStatus = RUNNING;
-
     try
     {
-        mThreadp = new std::thread(std::bind(&LLThread::threadRun, this));
-        mNativeHandle = mThreadp->native_handle();
+        mThreadp = std::make_unique<std::thread>(std::bind(&LLThread::threadRun, this));
 	}
 	catch (const std::system_error& err)
 	{
 		mStatus = CRASHED;
 		LL_WARNS() << "Failed to start thread: \"" << mName << "\" due to error: " << err.what() << LL_ENDL;
 	}
+    catch (const std::bad_alloc& err)
+	{
+		mStatus = CRASHED;
+		LL_WARNS() << "Failed to allocate thread: \"" << mName << "\" due to error: " << err.what() << LL_ENDL;
+	}
+}
+
+LLThread::id_t LLThread::getID() const
+{
+    return mThreadp ? mThreadp->get_id() : std::thread::id();
 }
 
 //============================================================================
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index c0856548fa9..99d03708de2 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -83,23 +83,20 @@ class LL_COMMON_API LLThread
 
     LLVolatileAPRPool* getLocalAPRFilePool() { return mLocalAPRFilePoolp ; }
 
-    id_t getID() const { return mID; }
+    id_t getID() const;
 
 private:
     bool                mPaused;
-    std::thread::native_handle_type mNativeHandle; // for termination in case of issues
-    
+
     // static function passed to APR thread creation routine
     void threadRun();
 
 protected:
     std::string         mName;
-    class LLCondition*  mRunCondition;
-    LLMutex*            mDataLock;
-
-    std::thread        *mThreadp;
-    EThreadStatus       mStatus;
-    id_t                mID;
+    std::unique_ptr<class LLCondition>  mRunCondition;
+    std::unique_ptr<LLMutex>            mDataLock;
+    std::unique_ptr<std::thread>        mThreadp;
+    std::atomic_int                     mStatus;
 #ifndef LL_RELEASE_FOR_DOWNLOAD
     LLTrace::ThreadRecorder* mRecorder;
 #endif
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 3d9db3dc538..b04a255c50f 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -1411,7 +1411,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry)
 			LLCore::HttpHandle handle = getByteRange(http_url, legacy_cap_version, info.mOffset, info.mSize, handler);
 			if (LLCORE_HTTP_HANDLE_INVALID == handle)
 			{
-				LL_WARNS(LOG_MESH) << "HTTP GET request failed for skin info on mesh " << mID
+				LL_WARNS(LOG_MESH) << "HTTP GET request failed for skin info on mesh " << getID()
 								   << ".  Reason:  " << mHttpStatus.toString()
 								   << " (" << mHttpStatus.toTerseString() << ")"
 								   << LL_ENDL;
@@ -1469,7 +1469,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
 			LLCore::HttpHandle handle = getByteRange(http_url, legacy_cap_version, info.mOffset, info.mSize, handler);
 			if (LLCORE_HTTP_HANDLE_INVALID == handle)
 			{
-				LL_WARNS(LOG_MESH) << "HTTP GET request failed for decomposition mesh " << mID
+				LL_WARNS(LOG_MESH) << "HTTP GET request failed for decomposition mesh " << getID()
 								   << ".  Reason:  " << mHttpStatus.toString()
 								   << " (" << mHttpStatus.toTerseString() << ")"
 								   << LL_ENDL;
@@ -1511,7 +1511,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
 			LLCore::HttpHandle handle = getByteRange(http_url, legacy_cap_version, info.mOffset, info.mSize, handler);
 			if (LLCORE_HTTP_HANDLE_INVALID == handle)
 			{
-				LL_WARNS(LOG_MESH) << "HTTP GET request failed for physics shape on mesh " << mID
+				LL_WARNS(LOG_MESH) << "HTTP GET request failed for physics shape on mesh " << getID()
 									<< ".  Reason:  " << mHttpStatus.toString()
 									<< " (" << mHttpStatus.toTerseString() << ")"
 									<< LL_ENDL;
@@ -1613,7 +1613,7 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, bool c
 		LLCore::HttpHandle handle = getByteRange(http_url, legacy_cap_version, 0, MESH_HEADER_SIZE, handler);
 		if (LLCORE_HTTP_HANDLE_INVALID == handle)
 		{
-			LL_WARNS(LOG_MESH) << "HTTP GET request failed for mesh header " << mID
+			LL_WARNS(LOG_MESH) << "HTTP GET request failed for mesh header " << getID()
 							   << ".  Reason:  " << mHttpStatus.toString()
 							   << " (" << mHttpStatus.toTerseString() << ")"
 							   << LL_ENDL;
@@ -1661,7 +1661,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod,
 			LLCore::HttpHandle handle = getByteRange(http_url, legacy_cap_version, info.mOffset, info.mSize, handler);
 			if (LLCORE_HTTP_HANDLE_INVALID == handle)
 			{
-				LL_WARNS(LOG_MESH) << "HTTP GET request failed for LOD on mesh " << mID
+				LL_WARNS(LOG_MESH) << "HTTP GET request failed for LOD on mesh " << getID()
 									<< ".  Reason:  " << mHttpStatus.toString()
 									<< " (" << mHttpStatus.toTerseString() << ")"
 									<< LL_ENDL;
-- 
GitLab