summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Lihatskiy <alihatskiy@productengine.com>2026-08-12 18:52:57 +0300
committerAndrey Lihatskiy <118752495+marchcat@users.noreply.github.com>2026-08-12 20:15:39 +0300
commit21bb60fc65e7fa6c3cf472a29cda220f653af1d8 (patch)
tree5be94310d9a9f25ac80cc2227638b224d079b71d
parentf6fa702706aeba8c5a3760a98883943cba3c973b (diff)
#6117 Guard against stale nearby chat toast handles
-rw-r--r--indra/newview/llfloaterimnearbychathandler.cpp59
1 files changed, 53 insertions, 6 deletions
diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp
index 3f1fe50b73..e92672f684 100644
--- a/indra/newview/llfloaterimnearbychathandler.cpp
+++ b/indra/newview/llfloaterimnearbychathandler.cpp
@@ -145,6 +145,8 @@ protected:
void updateToastFadingTime();
+ LLToast* getToastFromPool();
+
create_toast_panel_callback_t m_create_toast_panel_callback_t;
bool createPoolToast();
@@ -238,9 +240,19 @@ void LLFloaterIMNearbyChatScreenChannel::updateToastsLifetime()
S32 seconds = gSavedSettings.getS32("NearbyToastLifeTime");
toast_list_t::iterator it;
- for(it = m_toast_pool.begin(); it != m_toast_pool.end(); ++it)
+ for(it = m_toast_pool.begin(); it != m_toast_pool.end();)
{
- (*it).get()->setLifetime(seconds);
+ LLToast* toast = it->get();
+ if (toast)
+ {
+ toast->setLifetime(seconds);
+ ++it;
+ }
+ else
+ {
+ LL_WARNS("NearbyChat") << "Discarding destroyed toast from pool" << LL_ENDL;
+ it = m_toast_pool.erase(it);
+ }
}
}
@@ -249,12 +261,38 @@ void LLFloaterIMNearbyChatScreenChannel::updateToastFadingTime()
S32 seconds = gSavedSettings.getS32("NearbyToastFadingTime");
toast_list_t::iterator it;
- for(it = m_toast_pool.begin(); it != m_toast_pool.end(); ++it)
+ for(it = m_toast_pool.begin(); it != m_toast_pool.end();)
{
- (*it).get()->setFadingTime(seconds);
+ LLToast* toast = it->get();
+ if (toast)
+ {
+ toast->setFadingTime(seconds);
+ ++it;
+ }
+ else
+ {
+ LL_WARNS("NearbyChat") << "Discarding destroyed toast from pool" << LL_ENDL;
+ it = m_toast_pool.erase(it);
+ }
}
}
+LLToast* LLFloaterIMNearbyChatScreenChannel::getToastFromPool()
+{
+ while (!m_toast_pool.empty())
+ {
+ LLToast* toast = m_toast_pool.back().get();
+ m_toast_pool.pop_back();
+
+ if (toast)
+ return toast;
+
+ LL_WARNS("NearbyChat") << "Discarding destroyed toast from pool" << LL_ENDL;
+ }
+
+ return nullptr;
+}
+
bool LLFloaterIMNearbyChatScreenChannel::createPoolToast()
{
LLFloaterIMNearbyChatToastPanel* panel= m_create_toast_panel_callback_t();
@@ -344,9 +382,18 @@ void LLFloaterIMNearbyChatScreenChannel::addChat(LLSD& chat)
//take 1st element from pool, (re)initialize it, put it in active toasts
LL_DEBUGS("NearbyChat") << "Getting toast from pool" << LL_ENDL;
- LLToast* toast = m_toast_pool.back().get();
+ LLToast* toast = getToastFromPool();
+ if (!toast)
+ {
+ // A toast can be destroyed while its handle remains in the pool.
+ // Replenish the pool instead of dereferencing the dead handle.
+ if (!createPoolToast())
+ return;
- m_toast_pool.pop_back();
+ toast = getToastFromPool();
+ if (!toast)
+ return;
+ }
LLFloaterIMNearbyChatToastPanel* panel = dynamic_cast<LLFloaterIMNearbyChatToastPanel*>(toast->getPanel());