diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index fbdf08d8aaa10098bfd3ad7e10f5c2ad1011293e..4cfde21e328fa91c45d0992097019046f562b003 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 e30bfbb7591fb738edf0dbb80540d5bb3ecbbb91..787deeb594036efa3043bc7564c871d3e63ac644 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -165,7 +165,7 @@ class LLConversationItemSession : public LLConversationItem 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 71346b4b43c6ffa72c9be193cdceb2c316a9ced6..df16868132c1792ec0122651ba8693f1cfaab736 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();