From 21bb60fc65e7fa6c3cf472a29cda220f653af1d8 Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Wed, 12 Aug 2026 18:52:57 +0300 Subject: #6117 Guard against stale nearby chat toast handles --- indra/newview/llfloaterimnearbychathandler.cpp | 59 +++++++++++++++++++++++--- 1 file 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(toast->getPanel()); -- cgit v1.3