From bd86aed0750647ede14b1aea9284171719d29406 Mon Sep 17 00:00:00 2001 From: Ross Barnes-Brown <128988672+Quinn-Elara@users.noreply.github.com> Date: Tue, 7 Jul 2026 12:12:14 +0100 Subject: [PATCH 1/2] Fix another outfit-related CTD Defers notifying observers to run on the main thread. Fixes a CTD wherein glyph creation could happen outside of the main thread which would cause a CTD if uncaught. --- indra/newview/llaisapi.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index a1191e8a31..73dfa9910f 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -1683,7 +1683,11 @@ void AISUpdate::doUpdate() // fetching can receive massive amount of items and folders if (gInventory.getChangedIDs().size() > MAX_UPDATE_BACKLOG) { - gInventory.notifyObservers(); + LLAppViewer::instance()->postToMainCoro( + []() + { + gInventory.notifyObservers(); + }); checkTimeout(); } } @@ -1744,7 +1748,11 @@ void AISUpdate::doUpdate() // fetching can receive massive amount of items and folders if (gInventory.getChangedIDs().size() > MAX_UPDATE_BACKLOG) { - gInventory.notifyObservers(); + LLAppViewer::instance()->postToMainCoro( + []() + { + gInventory.notifyObservers(); + }); checkTimeout(); } } @@ -1815,6 +1823,10 @@ void AISUpdate::doUpdate() checkTimeout(); - gInventory.notifyObservers(); + LLAppViewer::instance()->postToMainCoro( + []() + { + gInventory.notifyObservers(); + }); } From 6c2da73f60e1637b4c7dab6ec053f533cb214bc0 Mon Sep 17 00:00:00 2001 From: Ross Barnes-Brown <128988672+Quinn-Elara@users.noreply.github.com> Date: Tue, 7 Jul 2026 13:42:39 +0100 Subject: [PATCH 2/2] Address llaisapi review comments --- indra/newview/llaisapi.cpp | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 73dfa9910f..a5dca715cb 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -1044,6 +1044,13 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht U32 AISUpdate::sBatchFrameCount = 0; LLTimer AISUpdate::sBatchTimer; +// Coalesces the deferred gInventory::notifyObservers() calls issued below +// when the change backlog exceeds MAX_UPDATE_BACKLOG, so repeated iterations +// while the backlog remains large don't flood gMainloopWork with duplicate +// postToMainCoro callbacks. Cleared once the posted callback actually runs +// notifyObservers(). +static bool sAISNotifyObserversPending = false; + AISUpdate::AISUpdate(const LLSD& update, AISAPI::COMMAND_TYPE type, const LLSD& request_body) : mType(type) { @@ -1683,11 +1690,16 @@ void AISUpdate::doUpdate() // fetching can receive massive amount of items and folders if (gInventory.getChangedIDs().size() > MAX_UPDATE_BACKLOG) { - LLAppViewer::instance()->postToMainCoro( - []() - { - gInventory.notifyObservers(); - }); + if (!sAISNotifyObserversPending) + { + sAISNotifyObserversPending = true; + LLAppViewer::instance()->postToMainCoro( + []() + { + gInventory.notifyObservers(); + sAISNotifyObserversPending = false; + }); + } checkTimeout(); } } @@ -1748,11 +1760,16 @@ void AISUpdate::doUpdate() // fetching can receive massive amount of items and folders if (gInventory.getChangedIDs().size() > MAX_UPDATE_BACKLOG) { - LLAppViewer::instance()->postToMainCoro( - []() - { - gInventory.notifyObservers(); - }); + if (!sAISNotifyObserversPending) + { + sAISNotifyObserversPending = true; + LLAppViewer::instance()->postToMainCoro( + []() + { + gInventory.notifyObservers(); + sAISNotifyObserversPending = false; + }); + } checkTimeout(); } } @@ -1829,4 +1846,3 @@ void AISUpdate::doUpdate() gInventory.notifyObservers(); }); } -