From db161b6f85a266ee9d883e3180874de898ccda0e Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 5 Jan 2021 18:20:30 +0200
Subject: [PATCH] SL-14074 Resolved potential cause of conversation crashes

Models (listeners) belong to folder-views, deleting all of them means that not only proper cleanup procedure won't be followed, and view might try clean dead pointer.
---
 indra/llui/llfolderviewmodel.h        | 6 +++---
 indra/newview/llconversationmodel.cpp | 3 +++
 indra/newview/llparticipantlist.cpp   | 7 ++-----
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h
index 84a15390944..4739d4e6fef 100644
--- a/indra/llui/llfolderviewmodel.h
+++ b/indra/llui/llfolderviewmodel.h
@@ -204,6 +204,7 @@ class LLFolderViewModelItem : public LLRefCount, public LLTrace::MemTrackable<LL
 	virtual bool hasChildren() const = 0;
 	virtual void addChild(LLFolderViewModelItem* child) = 0;
 	virtual void removeChild(LLFolderViewModelItem* child) = 0;
+	virtual void clearChildren() = 0;
 
 	// This method will be called to determine if a drop can be
 	// performed, and will set drop to TRUE if a drop is
@@ -301,9 +302,8 @@ class LLFolderViewModelItemCommon : public LLFolderViewModelItem
 	
 	virtual void clearChildren()
 	{
-		// As this is cleaning the whole list of children wholesale, we do need to delete the pointed objects
-		// This is different and not equivalent to calling removeChild() on each child
-		std::for_each(mChildren.begin(), mChildren.end(), DeletePointer());
+		// We are working with models that belong to views as LLPointers, clean the list, let poiters handle the rest
+		std::for_each(mChildren.begin(), mChildren.end(), [](LLFolderViewModelItem* c) {c->setParent(NULL); });
 		mChildren.clear();
 		dirtyDescendantsFilter();
 		dirtyFilter();
diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp
index 4aa74a550cb..8293dc6922c 100644
--- a/indra/newview/llconversationmodel.cpp
+++ b/indra/newview/llconversationmodel.cpp
@@ -341,6 +341,9 @@ void LLConversationItemSession::removeParticipant(const LLUUID& participant_id)
 
 void LLConversationItemSession::clearParticipants()
 {
+    // clearParticipants function potentially is malfunctioning since it only cleans children of models,
+    // it does nothing to views that own those models (listeners)
+    // probably needs to post some kind of 'remove all participants' event
 	clearChildren();
 	mIsLoaded = false;
 	mNeedsRefresh = true;
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index ee6893907e2..94d20828ecc 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -259,11 +259,7 @@ LLParticipantList::~LLParticipantList()
 */
 void LLParticipantList::onAvalineCallerFound(const LLUUID& participant_id)
 {
-	LLConversationItemParticipant* participant = findParticipant(participant_id);
-	if (participant)
-	{
-		removeParticipant(participant);
-	}
+	removeParticipant(participant_id);
 	// re-add avaline caller with a correct class instance.
 	addAvatarIDExceptAgent(participant_id);
 }
@@ -397,6 +393,7 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id)
 	// Hack for this: LLAvatarTracker::instance().isBuddyOnline(avatar_id))
 	
 	// Add the participant model to the session's children list
+	// This will post "add_participant" event
 	addParticipant(participant);
 
 	adjustParticipant(avatar_id);
-- 
GitLab