diff options
author | Andrey Kleshchev <andreykproductengine@lindenlab.com> | 2021-03-31 21:45:35 +0300 |
---|---|---|
committer | Andrey Kleshchev <andreykproductengine@lindenlab.com> | 2021-04-01 20:56:19 +0300 |
commit | 18323f019f51a0ca27470ec770232fc4618fcd4b (patch) | |
tree | 28aa7776d41eff0e8d40c0d26edae112060c5648 | |
parent | 6240168f24289517f9e84ac43076ca4f921c3e68 (diff) |
SL-15061 Crash deleting non-zero reference in LLConversationItemSession
-rw-r--r-- | indra/newview/llconversationmodel.cpp | 28 | ||||
-rw-r--r-- | indra/newview/llconversationmodel.h | 2 | ||||
-rw-r--r-- | indra/newview/llconversationview.cpp | 9 |
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(); |