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); | 
