summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Kleshchev <andreykproductengine@lindenlab.com>2024-02-23 04:18:03 +0200
committerAndrey Kleshchev <117672381+akleshchev@users.noreply.github.com>2024-02-23 19:18:13 +0200
commit5dcc0606a8512159660c652cb25e7f29292f2df0 (patch)
tree9566f92e9b2d4089e6ae18f9268878eff5e1a4ca
parent31af3d2b20f910f29747ddda10d31b05219532bd (diff)
Issue#880 Crash on a dead pointer in a chat session
-rw-r--r--indra/newview/llconversationmodel.cpp26
-rw-r--r--indra/newview/llfloaterimsessiontab.cpp41
2 files changed, 53 insertions, 14 deletions
diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp
index 9ec4fb085b..fe5428d7f5 100644
--- a/indra/newview/llconversationmodel.cpp
+++ b/indra/newview/llconversationmodel.cpp
@@ -353,22 +353,20 @@ void LLConversationItemSession::clearParticipants()
void LLConversationItemSession::clearAndDeparentModels()
{
- std::for_each(mChildren.begin(), mChildren.end(),
- [](LLFolderViewModelItem* c)
+ for (LLFolderViewModelItem* child : mChildren)
+ {
+ if (child->getNumRefs() == 0)
+ {
+ // LLConversationItemParticipant can be created but not assigned to any view,
+ // it was waiting for an "add_participant" event to be processed
+ delete child;
+ }
+ else
{
- if (c->getNumRefs() == 0)
- {
- // LLConversationItemParticipant can be created but not assigned to any view,
- // it was waiting for an "add_participant" event to be processed
- delete c;
- }
- else
- {
- // Model is still assigned to some view/widget
- c->setParent(NULL);
- }
+ // Model is still assigned to some view/widget
+ child->setParent(NULL);
}
- );
+ }
mChildren.clear();
}
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index 005e9f68ee..6c2649984f 100644
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -99,6 +99,26 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id)
LLFloaterIMSessionTab::~LLFloaterIMSessionTab()
{
delete mRefreshTimer;
+
+ LLFloaterIMContainer* im_container = LLFloaterIMContainer::findInstance();
+ if (im_container)
+ {
+ LLParticipantList* session = dynamic_cast<LLParticipantList*>(im_container->getSessionModel(mSessionID));
+ if (session)
+ {
+ for (const conversations_widgets_map::value_type& widget_pair : mConversationsWidgets)
+ {
+ LLFolderViewItem* widget = widget_pair.second;
+ LLFolderViewModelItem* item_vmi = widget->getViewModelItem();
+ if (item_vmi && item_vmi->getNumRefs() == 1)
+ {
+ // This is the last pointer, remove participant from session
+ // before participant gets deleted on destroyView.
+ session->removeChild(item_vmi);
+ }
+ }
+ }
+ }
}
//static
@@ -545,6 +565,27 @@ void LLFloaterIMSessionTab::removeConversationViewParticipant(const LLUUID& part
LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,participant_id);
if (widget)
{
+ LLFolderViewModelItem* item_vmi = widget->getViewModelItem();
+ if (item_vmi && item_vmi->getNumRefs() == 1)
+ {
+ // This is the last pointer, remove participant from session
+ // before participant gets deleted on destroyView.
+ //
+ // Floater (widget) and participant's view can simultaneously
+ // co-own the model, in which case view is responsible for
+ // the deletion and floater is free to clear and recreate
+ // the list, yet there are cases where only widget owns
+ // the pointer so it should do the cleanup.
+ // See "add_participant".
+ //
+ // Todo: If it keeps causing issues turn participants
+ // into LLPointers in the session
+ LLParticipantList* session = getParticipantList();
+ if (session)
+ {
+ session->removeChild(item_vmi);
+ }
+ }
widget->destroyView();
}
mConversationsWidgets.erase(participant_id);