From 0edbd2bdbf2109fbf5dcd1a013fe3febec255ffd Mon Sep 17 00:00:00 2001 From: matt kuhlenschmidt Date: Mon, 15 Jul 2019 21:08:31 -0400 Subject: [PATCH] Fix shutdown crash that happens because a widget is destroyed and isnt removed from an invalidation root because the invalidation root been disabled from using the fast path #ROBOMERGE-SOURCE: CL 7305300 via CL 7305301 via CL 7310315 #ROBOMERGE-BOT: (v371-7306989) [CL 7317160 by matt kuhlenschmidt in Main branch] --- .../FastUpdate/SlateInvalidationRoot.cpp | 23 +++++++++++++++++++ .../SlateCore/Private/Widgets/SWidget.cpp | 18 +-------------- .../Public/FastUpdate/SlateInvalidationRoot.h | 1 + .../SlateCore/Public/FastUpdate/WidgetProxy.h | 2 +- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/Engine/Source/Runtime/SlateCore/Private/FastUpdate/SlateInvalidationRoot.cpp b/Engine/Source/Runtime/SlateCore/Private/FastUpdate/SlateInvalidationRoot.cpp index e1bc5cebc260..d0b636215eff 100644 --- a/Engine/Source/Runtime/SlateCore/Private/FastUpdate/SlateInvalidationRoot.cpp +++ b/Engine/Source/Runtime/SlateCore/Private/FastUpdate/SlateInvalidationRoot.cpp @@ -56,6 +56,8 @@ FSlateInvalidationRoot::~FSlateInvalidationRoot() { delete CachedElementData; } + + CachedElementData = nullptr; } void FSlateInvalidationRoot::AddReferencedObjects(FReferenceCollector& Collector) @@ -238,6 +240,27 @@ FSlateInvalidationResult FSlateInvalidationRoot::PaintInvalidationRoot(const FSl return Result; } +void FSlateInvalidationRoot::OnWidgetDestroyed(const SWidget* Widget) +{ + InvalidateChildOrder(); + + // We need the index even if we've invalidated this root. We need to clear out its proxy regardless + const bool bEvenIfInvalid = true; + const int32 ProxyIndex = Widget->FastPathProxyHandle.GetIndex(bEvenIfInvalid); + if (FastWidgetPathList.IsValidIndex(ProxyIndex) && FastWidgetPathList[ProxyIndex].Widget == Widget) + { + FastWidgetPathList[ProxyIndex].Widget = nullptr; + + } + + if (Widget->PersistentState.CachedElementListNode) + { + CachedElementData->RemoveCache(Widget->PersistentState.CachedElementListNode); + } + + Widget->PersistentState.CachedElementListNode = nullptr; +} + bool FSlateInvalidationRoot::PaintFastPath(const FSlateInvalidationContext& Context) { SCOPED_NAMED_EVENT(SWidget_FastPathUpdate, FColor::Green); diff --git a/Engine/Source/Runtime/SlateCore/Private/Widgets/SWidget.cpp b/Engine/Source/Runtime/SlateCore/Private/Widgets/SWidget.cpp index dc3088ca57ca..04b520e9d72a 100644 --- a/Engine/Source/Runtime/SlateCore/Private/Widgets/SWidget.cpp +++ b/Engine/Source/Runtime/SlateCore/Private/Widgets/SWidget.cpp @@ -181,25 +181,9 @@ SWidget::~SWidget() FSlateApplicationBase::Get().UnRegisterActiveTimer(ActiveTimerHandle); } - if (FastPathProxyHandle.IsValid()) - { - FWidgetProxy& Proxy = FastPathProxyHandle.GetProxy(); - Proxy.Widget = nullptr; - } - else - { - ensure(FastPathProxyHandle.GetIndex() == INDEX_NONE); - } - if (FSlateInvalidationRoot* Root = FastPathProxyHandle.GetInvalidationRoot()) { - Root->InvalidateChildOrder(); - - if (PersistentState.CachedElementListNode) - { - Root->GetCachedElements().RemoveCache(PersistentState.CachedElementListNode); - } - + Root->OnWidgetDestroyed(this); } // Reset handle diff --git a/Engine/Source/Runtime/SlateCore/Public/FastUpdate/SlateInvalidationRoot.h b/Engine/Source/Runtime/SlateCore/Public/FastUpdate/SlateInvalidationRoot.h index d76356b962af..b4f006221104 100644 --- a/Engine/Source/Runtime/SlateCore/Public/FastUpdate/SlateInvalidationRoot.h +++ b/Engine/Source/Runtime/SlateCore/Public/FastUpdate/SlateInvalidationRoot.h @@ -82,6 +82,7 @@ public: SLATECORE_API FSlateInvalidationResult PaintInvalidationRoot(const FSlateInvalidationContext& Context); + void OnWidgetDestroyed(const SWidget* Widget); protected: virtual int32 PaintSlowPath(const FSlateInvalidationContext& Context) = 0; diff --git a/Engine/Source/Runtime/SlateCore/Public/FastUpdate/WidgetProxy.h b/Engine/Source/Runtime/SlateCore/Public/FastUpdate/WidgetProxy.h index 7d19d6cb9bed..98f18b0b7b0e 100644 --- a/Engine/Source/Runtime/SlateCore/Public/FastUpdate/WidgetProxy.h +++ b/Engine/Source/Runtime/SlateCore/Public/FastUpdate/WidgetProxy.h @@ -204,7 +204,7 @@ public: FWidgetProxy& GetProxy(); const FWidgetProxy& GetProxy() const; - int32 GetIndex() const { return IsValid() ? MyIndex : INDEX_NONE; } + int32 GetIndex(bool bEvenIfInvalid = false) const { return bEvenIfInvalid || IsValid() ? MyIndex : INDEX_NONE; } /** * Marks the widget as updated this frame