SL-15061 Crash deleting non-zero reference in LLConversationItemSession

meow-7.2.2
Andrey Kleshchev 2021-03-31 21:45:35 +03:00
parent 6240168f24
commit 18323f019f
3 changed files with 22 additions and 15 deletions

View File

@ -350,16 +350,24 @@ void LLConversationItemSession::clearParticipants()
}
void LLConversationItemSession::deleteParticipantModels()
void LLConversationItemSession::clearAndDeparentModels()
{
// 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());
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();
}

View File

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

View File

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