HaikuDepot: Keep reference to PackageInfos longer...

... in PackageInfoView::SetPackage() and Clear(). The sub-views reference
stuff from the previous PackageInfo instance. If we release the reference
before adopting the new package, the sub-views may still access stuff from
the previous package. For example the PackageActionView tries to avoid
rebuilding the button list and compares previous package actions to the
new actions. Particularily after the package list has been rebuild, we have
only new PackageInfo instances and the PackageInfoView may hold on to a
PackageInfo that is not still referenced anywhere else. Would be a good
explanation for #11785.
This commit is contained in:
Stephan Aßmus 2015-01-25 10:04:23 +01:00
parent 08e6e2aef8
commit 4a1fc9b122

View File

@ -533,7 +533,7 @@ public:
}
fPackageActions = actions;
if (!clearNeeded) {
if (!clearNeeded && fButtons.CountItems() == actions.CountItems()) {
int32 index = 0;
for (int32 i = fPackageActions.CountItems() - 1; i >= 0; i--) {
const PackageActionRef& action = fPackageActions.ItemAtFast(i);
@ -1438,9 +1438,26 @@ PackageInfoView::SetPackage(const PackageInfoRef& packageRef)
{
BAutolock _(fModelLock);
bool switchToDefaultTab = fPackage != packageRef;
fPackage = packageRef;
if (packageRef.Get() == NULL) {
Clear();
return;
}
bool switchToDefaultTab = true;
if (fPackage == packageRef) {
// When asked to display the already showing package ref,
// don't switch to the default tab.
switchToDefaultTab = false;
} else if (fPackage.Get() != NULL && packageRef.Get() != NULL
&& fPackage->Title() == packageRef->Title()) {
// When asked to display a different PackageInfo instance,
// but it has the same package title as the already showing
// instance, this probably means there was a repository
// refresh and we are in fact still requested to show the
// same package as before the refresh.
switchToDefaultTab = false;
}
const PackageInfo& package = *packageRef.Get();
fTitleView->SetPackage(package);
@ -1450,22 +1467,30 @@ PackageInfoView::SetPackage(const PackageInfoRef& packageRef)
fCardLayout->SetVisibleItem(1);
fPackageListener->SetPackage(packageRef);
// Set the fPackage reference last, so we keep a reference to the
// previous package before switching all the views to the new package.
// Otherwise the PackageInfo instance may go away because we had the
// last reference. And some of the views, the PackageActionView for
// example, keeps references to stuff from the previous package and
// access it while switching to the new package.
fPackage = packageRef;
}
void
PackageInfoView::Clear()
{
fPackage = PackageInfoRef(NULL);
BAutolock _(fModelLock);
fTitleView->Clear();
fPackageActionView->Clear();
fPagesView->Clear();
fCardLayout->SetVisibleItem((int32)0);
BAutolock _(fModelLock);
fPackageListener->SetPackage(PackageInfoRef(NULL));
fPackageListener->SetPackage(fPackage);
fPackage.Unset();
}