From 9c16cb4ca6e1db3d23fbf50369ac515333e0ff3f Mon Sep 17 00:00:00 2001 From: Rafal Walczyna Date: Fri, 9 Oct 2020 13:52:55 +0200 Subject: [PATCH] [Application] Add check for user_data availability in AppControl callback Sometimes result_callback from app-control fires after ApplicationInstance destructor. [verification] Build successful Change-Id: If60467db9e97573aedc4b888dfbe68f5e16390fc Signed-off-by: Rafal Walczyna --- src/application/application_manager.cc | 26 ++++++++++++++++++++++---- src/application/application_manager.h | 7 ++++++- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/application/application_manager.cc b/src/application/application_manager.cc index 4de3140f..5fe6bafd 100644 --- a/src/application/application_manager.cc +++ b/src/application/application_manager.cc @@ -107,6 +107,9 @@ const int kDefaultPeriodOfTime = 30; #endif } +std::set ApplicationManager::launch_app_control_set_global_{}; +std::mutex ApplicationManager::launch_app_control_set_mutex_{}; + ApplicationManager::ApplicationManager(ApplicationInstance& instance) : pkgmgr_client_handle_(nullptr), pkgmgr_client_uninstall_handle_(nullptr), @@ -139,10 +142,12 @@ ApplicationManager::~ApplicationManager() { // cannot be determined, reply_callback depends on application scenario, which // cannot be predicted. Moreover reply_callback is optional and can be called or not, // thus callback_data is relesed here at the end of application lifetime. - std::for_each(launch_app_control_set.begin(), launch_app_control_set.end(), + std::lock_guard lock(launch_app_control_set_mutex_); + std::for_each(launch_app_control_set_.begin(), launch_app_control_set_.end(), [](LaunchAppControlCallbackData* const& data) { LoggerD("Releasing callback data: %p", data); delete data; + launch_app_control_set_global_.erase(data); }); } @@ -482,8 +487,10 @@ void ApplicationManager::LaunchAppControl(const picojson::value& args) { LaunchAppControlCallbackData* callback_data = static_cast(user_data); - if (!callback_data) { - LoggerD("reply_callback failed: user_data is nullptr"); + + std::lock_guard lock(launch_app_control_set_mutex_); + if (!launch_app_control_set_global_.count(callback_data)) { + LoggerE("Invalid callback_data: %p", callback_data); return; } @@ -518,6 +525,12 @@ void ApplicationManager::LaunchAppControl(const picojson::value& args) { LaunchAppControlCallbackData* callback_data = static_cast(user_data); + std::lock_guard lock(launch_app_control_set_mutex_); + if (!launch_app_control_set_global_.count(callback_data)) { + LoggerE("Invalid callback_data: %p", callback_data); + return; + } + auto result = utils::TranslateAppControlError(launch_result); if (result.IsError()) { @@ -553,7 +566,12 @@ void ApplicationManager::LaunchAppControl(const picojson::value& args) { // Moreover reply_callback is optional and can be called or not, // thus callback_data is stored for releasing in destructor of ApplicationManager // at the end of application lifetime. - launch_app_control_set.insert(launch_app_user_data); + // We can not be sure whether callbach will not fire after instance destruction, + // we store all user_data pointers in static launch_app_control_set_global_ to check + // if they are still valid. + std::lock_guard lock(launch_app_control_set_mutex_); + launch_app_control_set_.insert(launch_app_user_data); + launch_app_control_set_global_.insert(launch_app_user_data); LoggerD("App launched, data %p stored for later release", launch_app_user_data); } } diff --git a/src/application/application_manager.h b/src/application/application_manager.h index 5a9d123b..0af43012 100644 --- a/src/application/application_manager.h +++ b/src/application/application_manager.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #if defined(TIZEN_MOBILE) @@ -89,7 +90,11 @@ class ApplicationManager { JsonCallback event_callback_; JsonCallback status_callback_; std::map event_handler_map_; - std::set launch_app_control_set; + std::set launch_app_control_set_; + // We use static set of callback_data's pointers to be able to check whether + // callback is fired after ApplicationInstance destruction + static std::set launch_app_control_set_global_; + static std::mutex launch_app_control_set_mutex_; static void OnEvent(const char* event_name, bundle* event_data, void* user_data); static void OnStatusEvent(const char* type, const char* app_id, app_manager_event_type_e event_type, -- 2.34.1