[Common] Keep track of created and destroyed instances. Safe PostMessage() method.
authorPawel Andruszkiewicz <p.andruszkie@samsung.com>
Thu, 27 Aug 2015 09:31:13 +0000 (11:31 +0200)
committerPawel Andruszkiewicz <p.andruszkie@samsung.com>
Thu, 27 Aug 2015 09:39:02 +0000 (11:39 +0200)
Fixes: XWALK-730
The PostMessage() method is usually called after asynchronous job executed in background.
Since the job may finish after an instance has been destroyed, it's not very safe. Some of the modules
have experienced this problem before, and had similar workaround implemented (i.e. Download).

This commit adds a common mechanism which keeps track of existing instances and provides safe PostMessage() method.

As a follow-up, the method 'void Instance::PostMessage(const char* msg)' should be made private and all existing
calls to that method should be replaced with calls to 'void Instance::PostMessage(Instance* that, const char* msg)'.

Change-Id: Icb0bd38516f8a8203d7c9ca28837c036a258f9b6
Signed-off-by: Pawel Andruszkiewicz <p.andruszkie@samsung.com>
src/application/application_manager.cc
src/common/extension.cc
src/common/extension.h

index c79db02448c605359b90b7a0e284be30ba5e3404..9da4a0fc939befacb4ce98c88525ee24fc2e9698 100755 (executable)
@@ -453,7 +453,7 @@ void ApplicationManager::Launch(const picojson::value& args) {
   };
 
   auto launch_response = [this](const std::shared_ptr<picojson::value>& response) -> void {
-    this->instance_.PostMessage(response->serialize().c_str());
+    Instance::PostMessage(&this->instance_, response->serialize().c_str());
   };
 
   TaskQueue::GetInstance().Queue<picojson::value>(launch, launch_response, response);
index 94ee30899c862c5b98c581c9b309b26f425d058f..c11d51252f13d3fdd0ee353a436a0d4ca97cd89a 100755 (executable)
@@ -255,18 +255,39 @@ int32_t Extension::XW_Initialize(XW_Extension extension,
   return XW_OK;
 }
 
+std::mutex Instance::instance_mutex_;
+std::unordered_set<Instance*> Instance::all_instances_;
 
 Instance::Instance() :
     xw_instance_(0)
 {
   LoggerD("Enter");
+  {
+    std::lock_guard<std::mutex> lock(instance_mutex_);
+    all_instances_.insert(this);
+  }
 }
 
 Instance::~Instance() {
   LoggerD("Enter");
+  {
+    std::lock_guard<std::mutex> lock(instance_mutex_);
+    all_instances_.erase(this);
+  }
   Assert(xw_instance_ == 0);
 }
 
+void Instance::PostMessage(Instance* that, const char* msg) {
+  LoggerD("Enter");
+  std::lock_guard<std::mutex> lock(instance_mutex_);
+  if (that && all_instances_.end() != all_instances_.find(that)) {
+    that->PostMessage(msg);
+  } else {
+    LoggerE("Trying to post message to non-existing instance: [%p], ignoring",
+            that);
+  }
+}
+
 void Instance::PostMessage(const char* msg) {
   LoggerD("Enter");
   if (!xw_instance_) {
index 7e67d2b49f8cd3c3bf64897a8e0646682f5b245f..3e65e8df566a802bbefa1636454e318a8fb5dd12 100755 (executable)
@@ -21,7 +21,9 @@
 
 #include <string>
 #include <map>
+#include <mutex>
 #include <functional>
+#include <unordered_set>
 
 #include "common/platform_exception.h"
 #include "common/platform_result.h"
@@ -102,6 +104,8 @@ class Instance {
   Instance();
   virtual ~Instance();
 
+  static void PostMessage(Instance* that, const char* msg);
+
   void PostMessage(const char* msg);
   void PostData(const char* msg, uint8_t* buffer, size_t len);
   void SendSyncReply(const char* reply);
@@ -120,6 +124,9 @@ class Instance {
  private:
   friend class Extension;
 
+  static std::mutex instance_mutex_;
+  static std::unordered_set<Instance*> all_instances_;
+
   XW_Instance xw_instance_;
 };