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 /indra/newview | |
| parent | 6240168f24289517f9e84ac43076ca4f921c3e68 (diff) | |
SL-15061 Crash deleting non-zero reference in LLConversationItemSession
Diffstat (limited to 'indra/newview')
| -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(); | 
