[Application] Add check for user_data availability in AppControl callback 61/245461/10
authorRafal Walczyna <r.walczyna@samsung.com>
Fri, 9 Oct 2020 11:52:55 +0000 (13:52 +0200)
committerRafal Walczyna <r.walczyna@samsung.com>
Tue, 20 Oct 2020 07:56:07 +0000 (09:56 +0200)
Sometimes result_callback from app-control fires after
ApplicationInstance destructor.

[verification] Build successful

Change-Id: If60467db9e97573aedc4b888dfbe68f5e16390fc
Signed-off-by: Rafal Walczyna <r.walczyna@samsung.com>
src/application/application_manager.cc
src/application/application_manager.h

index c1d84d2..039842b 100644 (file)
@@ -106,6 +106,9 @@ const int kDefaultPeriodOfTime = 30;
 #endif
 }
 
+std::set<LaunchAppControlCallbackData*> 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),
@@ -138,10 +141,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<std::mutex> 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);
                 });
 }
 
@@ -481,8 +486,10 @@ void ApplicationManager::LaunchAppControl(const picojson::value& args) {
 
       LaunchAppControlCallbackData* callback_data =
           static_cast<LaunchAppControlCallbackData*>(user_data);
-      if (!callback_data) {
-        LoggerD("reply_callback failed: user_data is nullptr");
+
+      std::lock_guard<std::mutex> lock(launch_app_control_set_mutex_);
+      if (!launch_app_control_set_global_.count(callback_data)) {
+        LoggerE("Invalid callback_data: %p", callback_data);
         return;
       }
 
@@ -517,6 +524,12 @@ void ApplicationManager::LaunchAppControl(const picojson::value& args) {
     LaunchAppControlCallbackData* callback_data =
         static_cast<LaunchAppControlCallbackData*>(user_data);
 
+    std::lock_guard<std::mutex> 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()) {
@@ -552,7 +565,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<std::mutex> 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);
   }
 }
index 5a9d123..0af4301 100644 (file)
@@ -24,6 +24,7 @@
 #include <pkgmgr-info.h>
 #include <functional>
 #include <memory>
+#include <mutex>
 #include <set>
 #include <string>
 #if defined(TIZEN_MOBILE)
@@ -89,7 +90,11 @@ class ApplicationManager {
   JsonCallback event_callback_;
   JsonCallback status_callback_;
   std::map<std::string, event_handler_h> event_handler_map_;
-  std::set<LaunchAppControlCallbackData*> launch_app_control_set;
+  std::set<LaunchAppControlCallbackData*> 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<LaunchAppControlCallbackData*> 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,