#3379 Crash on gIdleCallbacks iteration

master
Andrey Kleshchev 2025-04-12 10:16:34 +03:00
parent cfad42bea9
commit 1dacabe780
1 changed files with 16 additions and 4 deletions

View File

@ -1866,7 +1866,7 @@ void LLFolderViewFolder::onIdleUpdateFavorites(void* data)
LLFolderViewFolder* self = reinterpret_cast<LLFolderViewFolder*>(data);
if (self->mFavoritesDirtyFlags == 0)
{
LL_WARNS() << "Called onIdleUpdateFavorites without dirty flags set" << LL_ENDL;
// already processed either on previous run or by a different callback
gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, self);
return;
}
@ -1892,12 +1892,20 @@ void LLFolderViewFolder::onIdleUpdateFavorites(void* data)
parent->setHasFavorites(true);
if (parent->mFavoritesDirtyFlags)
{
gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, parent);
// Parent will remove onIdleUpdateFavorites later, don't remove now,
// We are inside gIdleCallbacks. Removing 'self' callback is safe,
// but removing 'parent' can invalidate following iterator
parent->mFavoritesDirtyFlags = 0;
}
parent = parent->getParentFolder();
}
}
else
{
LL_WARNS() << "FAVORITE_ADDED for a folder without favorites" << LL_ENDL;
self->mFavoritesDirtyFlags = 0;
gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, self);
}
}
else if (self->mFavoritesDirtyFlags > FAVORITE_ADDED)
{
@ -1950,7 +1958,9 @@ void LLFolderViewFolder::onIdleUpdateFavorites(void* data)
parent->setHasFavorites(true);
if (parent->mFavoritesDirtyFlags)
{
gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, parent);
// Parent will remove onIdleUpdateFavorites later, don't remove now,
// We are inside gIdleCallbacks. Removing 'self' callback is safe,
// but removing 'parent' can invalidate following iterator
parent->mFavoritesDirtyFlags = 0;
}
parent = parent->getParentFolder();
@ -1959,8 +1969,10 @@ void LLFolderViewFolder::onIdleUpdateFavorites(void* data)
}
if (parent->mFavoritesDirtyFlags)
{
// Parent will remove onIdleUpdateFavorites later, don't remove now.
// We are inside gIdleCallbacks. Removing 'self' callback is safe,
// but removing 'parent' can invalidate following iterator
parent->mFavoritesDirtyFlags = 0;
gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, parent);
}
parent = parent->getParentFolder();
}