summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Kleshchev <andreykproductengine@lindenlab.com>2021-03-31 21:45:35 +0300
committerAndrey Kleshchev <andreykproductengine@lindenlab.com>2021-04-01 20:56:19 +0300
commit18323f019f51a0ca27470ec770232fc4618fcd4b (patch)
tree28aa7776d41eff0e8d40c0d26edae112060c5648
parent6240168f24289517f9e84ac43076ca4f921c3e68 (diff)
SL-15061 Crash deleting non-zero reference in LLConversationItemSession
-rw-r--r--indra/newview/llconversationmodel.cpp28
-rw-r--r--indra/newview/llconversationmodel.h2
-rw-r--r--indra/newview/llconversationview.cpp9
3 files changed, 23 insertions, 16 deletions
diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp
index fbdf08d8aa..4cfde21e32 100644
--- a/indra/newview/llconversationmodel.cpp
+++ b/indra/newview/llconversationmodel.cpp
@@ -350,16 +350,24 @@ void LLConversationItemSession::clearParticipants()
}
-void LLConversationItemSession::deleteParticipantModels()
-{
- // Make sure that no views exist before use and that view-owned items were removed!
- //
- // Normally we are not supposed to delete models directly, they should be
- // owned by views and this action will result in crashes, but LLParticipantList
- // creates models separately from views (it probably shouldn't) and then those
- // models wait for idle cycles to be assigned to view.
- // this code is meant to delete 'waiting' models
- std::for_each(mChildren.begin(), mChildren.end(), DeletePointer());
+void LLConversationItemSession::clearAndDeparentModels()
+{
+ std::for_each(mChildren.begin(), mChildren.end(),
+ [](LLFolderViewModelItem* c)
+ {
+ 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);
+ }
+ }
+ );
mChildren.clear();
}
diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h
index e30bfbb759..787deeb594 100644
--- a/indra/newview/llconversationmodel.h
+++ b/indra/newview/llconversationmodel.h
@@ -165,7 +165,7 @@ public:
void removeParticipant(LLConversationItemParticipant* participant);
void removeParticipant(const LLUUID& participant_id);
void clearParticipants();
- void deleteParticipantModels(); // do not use while there are existing participant views
+ void clearAndDeparentModels(); // will delete unowned models and deparent owned ones
LLConversationItemParticipant* findParticipant(const LLUUID& participant_id);
void setParticipantIsMuted(const LLUUID& participant_id, bool is_muted);
diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp
index 71346b4b43..df16868132 100644
--- a/indra/newview/llconversationview.cpp
+++ b/indra/newview/llconversationview.cpp
@@ -108,8 +108,7 @@ void LLConversationViewSession::destroyView()
// Chat can create and parent models(listeners) to session's model before creating
// coresponding views, such participant's models normally will wait for idle cycles
// but since we are deleting session and won't be processing any more events, make
- // sure unowned models are removed as well.
- // Might be good idea to just have an LLPointer list somewhere in LLConversationItemSession
+ // sure unowned LLConversationItemParticipant models are removed as well.
LLConversationItemSession* vmi = dynamic_cast<LLConversationItemSession*>(getViewModelItem());
@@ -146,9 +145,9 @@ void LLConversationViewSession::destroyView()
folderp->destroyView();
}
- // Now everything that is left in model(listener) is unowned,
- // it is safe to remove
- vmi->deleteParticipantModels();
+ // Now everything that is left in model(listener) is not owned by views,
+ // only by sessions, deparent so it won't point to soon to be dead model
+ vmi->clearAndDeparentModels();
}
LLFolderViewFolder::destroyView();