From fcb17af2a1b8fbaf0ccf7fbcf6ec3d12c246d1c5 Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Sun, 30 Apr 2023 18:40:21 -0400
Subject: [PATCH] Fix shutdown crash

---
 indra/newview/llgltfmateriallist.cpp | 196 ++++++++++++++-------------
 1 file changed, 102 insertions(+), 94 deletions(-)

diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp
index ec19bb88df7..3baa7b227c8 100644
--- a/indra/newview/llgltfmateriallist.cpp
+++ b/indra/newview/llgltfmateriallist.cpp
@@ -223,100 +223,108 @@ class LLGLTFMaterialOverrideDispatchHandler : public LLDispatchHandler
             bool mSuccess;
         };
 
-        // fromJson() is performance heavy offload to a thread.
-        main_queue->postTo(
-            general_queue,
-            [object_override]() // Work done on general queue
-        {
-            std::vector<ReturnData> results;
-
-            if (!object_override.mSides.empty())
-            {
-                results.reserve(object_override.mSides.size());
-                // parse json
-                std::unordered_map<S32, std::string>::const_iterator iter = object_override.mSides.begin();
-                std::unordered_map<S32, std::string>::const_iterator end = object_override.mSides.end();
-                while (iter != end)
-                {
-                    LLPointer<LLGLTFMaterial> override_data = new LLGLTFMaterial();
-                    std::string warn_msg, error_msg;
-
-                    bool success = override_data->fromJSON(iter->second, warn_msg, error_msg);
-
-                    ReturnData result;
-                    result.mSuccess = success;
-                    result.mSide = iter->first;
-
-                    if (success)
-                    {
-                        result.mMaterial = override_data;
-                    }
-                    else
-                    {
-                        LL_WARNS("GLTF") << "failed to parse GLTF override data.  errors: " << error_msg << " | warnings: " << warn_msg << LL_ENDL;
-                    }
-
-                    results.push_back(result);
-                    iter++;
-                }
-            }
-            return results;
-        },
-            [object_override, this](std::vector<ReturnData> results) // Callback to main thread
-            {
-            LLViewerObject * obj = gObjectList.findObject(object_override.mObjectId);
-
-            if (results.size() > 0 )
-            {
-                std::unordered_set<S32> side_set;
-
-                for (int i = 0; i < results.size(); ++i)
-                {
-                    if (results[i].mSuccess)
-                    {
-                        // flag this side to not be nulled out later
-                        side_set.insert(results[i].mSide);
-
-                        if (obj)
-                        {
-                            obj->setTEGLTFMaterialOverride(results[i].mSide, results[i].mMaterial);
-                        }
-                    }
-                    
-                    // unblock material editor
-                    if (obj && obj->getTE(results[i].mSide) && obj->getTE(results[i].mSide)->isSelected())
-                    {
-                        doSelectionCallbacks(object_override.mObjectId, results[i].mSide);
-                    }
-                }
-
-                if (obj && side_set.size() != obj->getNumTEs())
-                { // object exists and at least one texture entry needs to have its override data nulled out
-                    for (int i = 0; i < obj->getNumTEs(); ++i)
-                    {
-                        if (side_set.find(i) == side_set.end())
-                        {
-                            obj->setTEGLTFMaterialOverride(i, nullptr);
-                            if (obj->getTE(i) && obj->getTE(i)->isSelected())
-                            {
-                                doSelectionCallbacks(object_override.mObjectId, i);
-                            }
-                        }
-                    }
-                }
-            }
-            else if (obj)
-            { // override list was empty or an error occurred, null out all overrides for this object
-                for (int i = 0; i < obj->getNumTEs(); ++i)
-                {
-                    obj->setTEGLTFMaterialOverride(i, nullptr);
-                    if (obj->getTE(i) && obj->getTE(i)->isSelected())
-                    {
-                        doSelectionCallbacks(obj->getID(), i);
-                    }
-                }
-            }
-        });
+		try
+		{
+			// fromJson() is performance heavy offload to a thread.
+			main_queue->postTo(
+				general_queue,
+				[object_override]() // Work done on general queue
+				{
+					std::vector<ReturnData> results;
+
+					if (!object_override.mSides.empty())
+					{
+						results.reserve(object_override.mSides.size());
+						// parse json
+						std::unordered_map<S32, std::string>::const_iterator iter = object_override.mSides.begin();
+						std::unordered_map<S32, std::string>::const_iterator end = object_override.mSides.end();
+						while (iter != end)
+						{
+							LLPointer<LLGLTFMaterial> override_data = new LLGLTFMaterial();
+							std::string warn_msg, error_msg;
+
+							bool success = override_data->fromJSON(iter->second, warn_msg, error_msg);
+
+							ReturnData result;
+							result.mSuccess = success;
+							result.mSide = iter->first;
+
+							if (success)
+							{
+								result.mMaterial = override_data;
+							}
+							else
+							{
+								LL_WARNS("GLTF") << "failed to parse GLTF override data.  errors: " << error_msg << " | warnings: " << warn_msg << LL_ENDL;
+							}
+
+							results.push_back(result);
+							iter++;
+						}
+					}
+					return results;
+				},
+				[object_override, this](std::vector<ReturnData> results) // Callback to main thread
+				{
+					LLViewerObject* obj = gObjectList.findObject(object_override.mObjectId);
+
+					if (results.size() > 0)
+					{
+						std::unordered_set<S32> side_set;
+
+						for (int i = 0; i < results.size(); ++i)
+						{
+							if (results[i].mSuccess)
+							{
+								// flag this side to not be nulled out later
+								side_set.insert(results[i].mSide);
+
+								if (obj)
+								{
+									obj->setTEGLTFMaterialOverride(results[i].mSide, results[i].mMaterial);
+								}
+							}
+
+							// unblock material editor
+							if (obj && obj->getTE(results[i].mSide) && obj->getTE(results[i].mSide)->isSelected())
+							{
+								doSelectionCallbacks(object_override.mObjectId, results[i].mSide);
+							}
+						}
+
+						if (obj && side_set.size() != obj->getNumTEs())
+						{ // object exists and at least one texture entry needs to have its override data nulled out
+							for (int i = 0; i < obj->getNumTEs(); ++i)
+							{
+								if (side_set.find(i) == side_set.end())
+								{
+									obj->setTEGLTFMaterialOverride(i, nullptr);
+									if (obj->getTE(i) && obj->getTE(i)->isSelected())
+									{
+										doSelectionCallbacks(object_override.mObjectId, i);
+									}
+								}
+							}
+						}
+					}
+					else if (obj)
+					{ // override list was empty or an error occurred, null out all overrides for this object
+						for (int i = 0; i < obj->getNumTEs(); ++i)
+						{
+							obj->setTEGLTFMaterialOverride(i, nullptr);
+							if (obj->getTE(i) && obj->getTE(i)->isSelected())
+							{
+								doSelectionCallbacks(obj->getID(), i);
+							}
+						}
+					}
+				});
+		}
+		catch (const LLThreadSafeQueueInterrupt&)
+		{
+			// Shutdown
+			LL_WARNS() << "Tried to start decoding on shutdown" << LL_ENDL;
+		}
     }
 
 private:
-- 
GitLab