diff options
author | Andrey Kleshchev <andreykproductengine@lindenlab.com> | 2024-02-23 04:18:03 +0200 |
---|---|---|
committer | Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> | 2024-02-23 19:18:13 +0200 |
commit | 5dcc0606a8512159660c652cb25e7f29292f2df0 (patch) | |
tree | 9566f92e9b2d4089e6ae18f9268878eff5e1a4ca | |
parent | 31af3d2b20f910f29747ddda10d31b05219532bd (diff) |
Issue#880 Crash on a dead pointer in a chat session
-rw-r--r-- | indra/newview/llconversationmodel.cpp | 26 | ||||
-rw-r--r-- | indra/newview/llfloaterimsessiontab.cpp | 41 |
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); |