From 9e11db9825d7e131d085b54113ee7654d43314df Mon Sep 17 00:00:00 2001 From: David Steele Date: Thu, 29 Oct 2020 16:58:41 +0000 Subject: [PATCH] Ensure AnimatedVectorImageVisual doesn't hang app Currently, if the AnimatedVectorImageVisual is not destroyed on Application::Terminate, e.g. if it's actor is kept alive, then the shutdown order is undefined, and may end up trying to pend on a mutex which has already been destroyed, in the dali-extension plugin. (TizenVectorAnimationManager, which creates the mutex, is a singleton that is created when first needed, but stays alive until main() completes) Prevented the destructor from finalizing in the plugin if core has already been shutdown. Change-Id: I9fe547eab4dc3f3e5a4655f5c8dcf96bf664d7e3 --- .../animated-vector-image-visual.cpp | 33 ++++++++++++++++------ .../animated-vector-image-visual.h | 10 ++++++- .../vector-animation-manager.cpp | 21 ++++++++++++++ .../vector-animation-manager.h | 17 +++++++++++ 4 files changed, 72 insertions(+), 9 deletions(-) diff --git a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp index ea097e1..fead0e6 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp @@ -94,25 +94,41 @@ AnimatedVectorImageVisual::AnimatedVectorImageVisual( VisualFactoryCache& factor mPlacementActor(), mPlayState( DevelImageVisual::PlayState::STOPPED ), mEventCallback( nullptr ), - mRendererAdded( false ) + mRendererAdded( false ), + mCoreShutdown(false) { // the rasterized image is with pre-multiplied alpha format mImpl->mFlags |= Impl::IS_PREMULTIPLIED_ALPHA; mVectorAnimationTask->UploadCompletedSignal().Connect( this, &AnimatedVectorImageVisual::OnUploadCompleted ); mVectorAnimationTask->SetAnimationFinishedCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnAnimationFinished ) ) ); + + auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager(); + vectorAnimationManager.AddObserver(*this); } AnimatedVectorImageVisual::~AnimatedVectorImageVisual() { - if( mEventCallback ) + if( ! mCoreShutdown ) { - mFactoryCache.GetVectorAnimationManager().UnregisterEventCallback( mEventCallback ); + auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager(); + vectorAnimationManager.RemoveObserver(*this); + + if( mEventCallback ) + { + mFactoryCache.GetVectorAnimationManager().UnregisterEventCallback( mEventCallback ); + } + + // Finalize animation task and disconnect the signal in the main thread + mVectorAnimationTask->UploadCompletedSignal().Disconnect( this, &AnimatedVectorImageVisual::OnUploadCompleted ); + mVectorAnimationTask->Finalize(); } +} - // Finalize animation task and disconnect the signal in the main thread - mVectorAnimationTask->UploadCompletedSignal().Disconnect( this, &AnimatedVectorImageVisual::OnUploadCompleted ); - mVectorAnimationTask->Finalize(); +void AnimatedVectorImageVisual::VectorAnimationManagerDestroyed() +{ + // Core is shutting down. Don't talk to the plugin any more. + mCoreShutdown = true; } void AnimatedVectorImageVisual::GetNaturalSize( Vector2& naturalSize ) @@ -500,10 +516,11 @@ void AnimatedVectorImageVisual::StopAnimation() void AnimatedVectorImageVisual::TriggerVectorRasterization() { - if( !mEventCallback ) + if( !mEventCallback && !mCoreShutdown ) { mEventCallback = MakeCallback( this, &AnimatedVectorImageVisual::OnProcessEvents ); - mFactoryCache.GetVectorAnimationManager().RegisterEventCallback( mEventCallback ); + auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager(); + vectorAnimationManager.RegisterEventCallback( mEventCallback ); Stage::GetCurrent().KeepRendering( 0.0f ); // Trigger event processing } } diff --git a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.h b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.h index e09527a..6196e39 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.h +++ b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.h @@ -30,6 +30,7 @@ #include #include #include +#include namespace Dali { @@ -55,7 +56,7 @@ using AnimatedVectorImageVisualPtr = IntrusivePtr< AnimatedVectorImageVisual >; * | url | STRING | * */ -class AnimatedVectorImageVisual: public Visual::Base, public ConnectionTracker +class AnimatedVectorImageVisual: public Visual::Base, public ConnectionTracker, public VectorAnimationManager::LifecycleObserver { public: @@ -97,6 +98,12 @@ public: // from Visual */ void DoCreateInstancePropertyMap( Property::Map& map ) const override; +protected: // From VectorAnimationManager::LifecycleObserver: + /** + * @copydoc VectorAnimationManager::LifecycleObserver::VectorAnimationManagerDestroyed() + */ + void VectorAnimationManagerDestroyed() override; + protected: /** @@ -221,6 +228,7 @@ private: DevelImageVisual::PlayState::Type mPlayState; CallbackBase* mEventCallback; // Not owned bool mRendererAdded; + bool mCoreShutdown; }; } // namespace Internal diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.cpp b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.cpp index 8e47d81..ad56227 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.cpp @@ -45,6 +45,7 @@ Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New( Debug::NoLogging, VectorAnimationManager::VectorAnimationManager() : mEventCallbacks(), + mLifecycleObservers(), mVectorAnimationThread( nullptr ), mProcessorRegistered( false ) { @@ -62,6 +63,26 @@ VectorAnimationManager::~VectorAnimationManager() { Adaptor::Get().UnregisterProcessor( *this ); } + + for( auto observer : mLifecycleObservers ) + { + observer->VectorAnimationManagerDestroyed(); + } +} + +void VectorAnimationManager::AddObserver( VectorAnimationManager::LifecycleObserver& observer ) +{ + DALI_ASSERT_DEBUG( mLifecycleObservers.end() == std::find( mLifecycleObservers.begin(), mLifecycleObservers.end(), &observer)); + mLifecycleObservers.push_back( &observer ); +} + +void VectorAnimationManager::RemoveObserver( VectorAnimationManager::LifecycleObserver& observer) +{ + auto iterator=std::find(mLifecycleObservers.begin(), mLifecycleObservers.end(), &observer); + if( iterator != mLifecycleObservers.end() ) + { + mLifecycleObservers.erase(iterator); + } } VectorAnimationThread& VectorAnimationManager::GetVectorAnimationThread() diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h index 510c07e..7fbc3ca 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h @@ -43,6 +43,10 @@ class VectorAnimationThread; class VectorAnimationManager: public Integration::Processor { public: + struct LifecycleObserver + { + virtual void VectorAnimationManagerDestroyed() = 0; + }; /** * @brief Constructor. @@ -55,6 +59,18 @@ public: ~VectorAnimationManager() override; /** + * Add a lifecycle observer + * @param[in] observer The object watching this one + */ + void AddObserver( LifecycleObserver& observer ); + + /** + * Remove a lifecycle observer + * @param[in] observer The object watching this one + */ + void RemoveObserver( LifecycleObserver& observer ); + + /** * Get the vector animation thread. * @return A raw pointer pointing to the vector animation thread. */ @@ -93,6 +109,7 @@ private: private: std::vector< CallbackBase* > mEventCallbacks; + std::vector mLifecycleObservers; std::unique_ptr< VectorAnimationThread > mVectorAnimationThread; bool mProcessorRegistered; }; -- 2.7.4