From: Eunki, Hong Date: Fri, 14 Jun 2024 05:02:48 +0000 (+0900) Subject: Fix assert when callback cancel timer during execute callback X-Git-Tag: dali_2.3.29~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=23997639945f3e84a5d4df06e5ba8da617c23cb3;p=platform%2Fcore%2Fuifw%2Fdali-adaptor.git Fix assert when callback cancel timer during execute callback It is possible that user can call CancelTimer during timer callback execute. If then, timerIter could be end. If this case, we should not move iterator into spent container. Change-Id: Ie28b9dfdddcc2a7ef300c783a9b50d5620761674 Signed-off-by: Eunki, Hong --- diff --git a/dali/internal/legacy/common/tizen-platform-abstraction.cpp b/dali/internal/legacy/common/tizen-platform-abstraction.cpp index e783f8f..2fed2c2 100644 --- a/dali/internal/legacy/common/tizen-platform-abstraction.cpp +++ b/dali/internal/legacy/common/tizen-platform-abstraction.cpp @@ -72,13 +72,18 @@ uint32_t TizenPlatformAbstraction::TimerCallback::sNextTimerId = 0; TizenPlatformAbstraction::TizenPlatformAbstraction() : mDataStoragePath(""), mTimerPairsWaiting(), - mTimerPairsSpent() - + mTimerPairsSpent(), + mCleanupIdleCallback(nullptr) { } TizenPlatformAbstraction::~TizenPlatformAbstraction() { + if(mCleanupIdleCallback && Dali::Adaptor::IsAvailable()) + { + Dali::Adaptor::Get().RemoveIdle(mCleanupIdleCallback); + mCleanupIdleCallback = nullptr; + } } ImageDimensions TizenPlatformAbstraction::GetClosestImageSize(const std::string& filename, @@ -202,20 +207,30 @@ uint32_t TizenPlatformAbstraction::StartTimer(uint32_t milliseconds, CallbackBas void TizenPlatformAbstraction::CancelTimer(uint32_t timerId) { - auto iter = std::remove_if( - mTimerPairsWaiting.begin(), mTimerPairsWaiting.end(), [&timerId](std::unique_ptr& timerCallbackPtr) { - if(timerCallbackPtr->mIdNumber == timerId) - { - timerCallbackPtr->mTimer.Stop(); - return true; - } - else - { - return false; - } - }); - - mTimerPairsWaiting.erase(iter, mTimerPairsWaiting.end()); + std::vector >::iterator timerIter = std::find_if(mTimerPairsWaiting.begin(), mTimerPairsWaiting.end(), [&timerId](std::unique_ptr& timerCallbackPtr) { + if(timerCallbackPtr->mIdNumber == timerId) + { + timerCallbackPtr->mTimer.Stop(); + return true; + } + else + { + return false; + } + }); + + if(timerIter == std::end(mTimerPairsWaiting)) + { + DALI_LOG_DEBUG_INFO("TimerId %u Cancelled duplicated.\n", timerId); + return; + } + + // Move the canceled item to the spent list. + std::move(timerIter, timerIter + 1, std::back_inserter(mTimerPairsSpent)); + + mTimerPairsWaiting.erase(timerIter, timerIter + 1); + + RequestCleanupTimers(); } void TizenPlatformAbstraction::RunTimerFunction(TimerCallback& timerPtr) @@ -226,26 +241,40 @@ void TizenPlatformAbstraction::RunTimerFunction(TimerCallback& timerPtr) if(timerIter == std::end(mTimerPairsWaiting)) { - DALI_ASSERT_DEBUG(false); + // It might be cancel during callback execute. + DALI_LOG_DEBUG_INFO("Timer might be cancelled during execute.\n"); + return; } - // ...and move it + // Move the executed item to the spent list. std::move(timerIter, timerIter + 1, std::back_inserter(mTimerPairsSpent)); mTimerPairsWaiting.erase(timerIter, timerIter + 1); - if(DALI_UNLIKELY(!Dali::Adaptor::IsAvailable() || !Dali::Adaptor::Get().AddIdle(MakeCallback(this, &TizenPlatformAbstraction::CleanupTimers), false))) - { - DALI_LOG_ERROR("Fail to add idle callback for timer function. Call it synchronously.\n"); - CleanupTimers(); - } + RequestCleanupTimers(); } void TizenPlatformAbstraction::CleanupTimers() { + // Idler callback called. Remove it. + mCleanupIdleCallback = nullptr; + mTimerPairsSpent.clear(); } +void TizenPlatformAbstraction::RequestCleanupTimers() +{ + if(!mCleanupIdleCallback) + { + mCleanupIdleCallback = MakeCallback(this, &TizenPlatformAbstraction::CleanupTimers); + if(DALI_UNLIKELY(!Dali::Adaptor::IsAvailable() || !Dali::Adaptor::Get().AddIdle(mCleanupIdleCallback, false))) + { + DALI_LOG_ERROR("Fail to add idle callback for timer function. Call it synchronously.\n"); + CleanupTimers(); + } + } +} + TizenPlatformAbstraction* CreatePlatformAbstraction() { return new TizenPlatformAbstraction(); diff --git a/dali/internal/legacy/common/tizen-platform-abstraction.h b/dali/internal/legacy/common/tizen-platform-abstraction.h index 995ca78..9cc7652 100644 --- a/dali/internal/legacy/common/tizen-platform-abstraction.h +++ b/dali/internal/legacy/common/tizen-platform-abstraction.h @@ -2,7 +2,7 @@ #define DALI_TIZEN_PLATFORM_ABSTRACTION_H /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -120,6 +120,11 @@ private: */ void RunTimerFunction(TimerCallback& timerPtr); + /** + * @brief Requests cleanup of timers into idler. + */ + void RequestCleanupTimers(); + TizenPlatformAbstraction(const TizenPlatformAbstraction&); ///< Undefined TizenPlatformAbstraction& operator=(const TizenPlatformAbstraction&); ///< Undefined @@ -127,6 +132,8 @@ private: std::vector > mTimerPairsWaiting; std::vector > mTimerPairsSpent; + + Dali::CallbackBase* mCleanupIdleCallback; }; /**