From 0f3af5aa90602ae60079d11615d8de0765084afe Mon Sep 17 00:00:00 2001 From: Heeyong Song Date: Tue, 14 Apr 2020 14:30:18 +0900 Subject: [PATCH] Fix a crash of the TextureManager The observer may be deleted during the UploadComplete callback. So disconnect the signal and erase the object from the list first. Change-Id: I614008c9a93025aef973dc8fcf38e1b578f8f35c --- .../src/dali-toolkit/utc-Dali-Control.cpp | 47 ++++++++++++++++++++++ .../internal/visuals/texture-manager-impl.cpp | 18 +++------ 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp index bd15bb0..5255f10 100755 --- a/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp @@ -74,6 +74,7 @@ static void TestKeyInputFocusCallback( Control control ) const char* TEST_LARGE_IMAGE_FILE_NAME = TEST_RESOURCE_DIR "/tbcol.png"; const char* TEST_IMAGE_FILE_NAME = TEST_RESOURCE_DIR "/gallery-small-1.jpg"; +const char* TEST_SVG_FILE_NAME = TEST_RESOURCE_DIR "/Kid1.svg"; Vector4 GetControlBackgroundColor( Control& control ) { @@ -87,6 +88,20 @@ Vector4 GetControlBackgroundColor( Control& control ) return color; } +bool gResourceReadySignalFired = false; + +void ResourceReadySignal( Control control ) +{ + if( control.GetVisualResourceStatus( Control::Property::BACKGROUND ) == Visual::ResourceStatus::FAILED ) + { + Property::Map propertyMap; + propertyMap.Insert( ImageVisual::Property::URL, TEST_SVG_FILE_NAME ); + control.SetProperty( Control::Property::BACKGROUND, propertyMap ); + } + + gResourceReadySignalFired = true; +} + } // namespace /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -986,6 +1001,38 @@ int UtcDaliControlResourcesReady(void) END_TEST; } +int UtcDaliControlResourcesReady02(void) +{ + ToolkitTestApplication application; + tet_infoline( "Change a resource during ResourceReady callback" ); + + gResourceReadySignalFired = false; + + Control control = Control::New(); + control.SetSize( 200.f, 200.f ); + control.ResourceReadySignal().Connect( &ResourceReadySignal ); + + Property::Map propertyMap; + propertyMap.Insert( ImageVisual::Property::URL, "invalid.jpg" ); + control.SetProperty( Control::Property::BACKGROUND, propertyMap ); + + Stage::GetCurrent().Add( control ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( control.IsResourceReady(), true, TEST_LOCATION ); + DALI_TEST_EQUALS( gResourceReadySignalFired, true, TEST_LOCATION ); + gResourceReadySignalFired = false; + + END_TEST; +} + int UtcDaliControlMarginProperty(void) { ToolkitTestApplication application; diff --git a/dali-toolkit/internal/visuals/texture-manager-impl.cpp b/dali-toolkit/internal/visuals/texture-manager-impl.cpp index b34b9f1..71385e2 100644 --- a/dali-toolkit/internal/visuals/texture-manager-impl.cpp +++ b/dali-toolkit/internal/visuals/texture-manager-impl.cpp @@ -1016,6 +1016,12 @@ void TextureManager::NotifyObservers( TextureInfo& textureInfo, bool success ) DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "NotifyObservers() url:%s loadState:%s\n", textureInfo.url.GetUrl().c_str(), GET_LOAD_STATE_STRING(textureInfo.loadState ) ); + // It is possible for the observer to be deleted. + // Disconnect and remove the observer first. + observer->DestructionSignal().Disconnect( this, &TextureManager::ObserverDestroyed ); + + info->observerList.Erase( info->observerList.begin() ); + if( info->loadPixelBuffer ) { observer->LoadComplete( success, info->pixelBuffer, info->url, info->preMultiplied ); @@ -1026,8 +1032,6 @@ void TextureManager::NotifyObservers( TextureInfo& textureInfo, bool success ) info->preMultiplied ); } - observer->DestructionSignal().Disconnect( this, &TextureManager::ObserverDestroyed ); - // Get the textureInfo from the container again as it may have been invalidated. int textureInfoIndex = GetCacheIndexFromId( textureId ); if( textureInfoIndex == INVALID_CACHE_INDEX) @@ -1035,16 +1039,6 @@ void TextureManager::NotifyObservers( TextureInfo& textureInfo, bool success ) break; // texture has been removed - can stop. } info = &mTextureInfoContainer[ textureInfoIndex ]; - - // remove the observer that was just triggered if it's still in the list - for( TextureInfo::ObserverListType::Iterator j = info->observerList.Begin(); j != info->observerList.End(); ++j ) - { - if( *j == observer ) - { - info->observerList.Erase( j ); - break; - } - } } mQueueLoadFlag = false; -- 2.7.4