From e3dc0bceb9ef653f87d766970f9f763e5416bdf1 Mon Sep 17 00:00:00 2001 From: Pawel Andruszkiewicz Date: Thu, 27 Aug 2015 11:31:13 +0200 Subject: [PATCH] [Common] Keep track of created and destroyed instances. Safe PostMessage() method. 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 --- src/application/application_manager.cc | 2 +- src/common/extension.cc | 21 +++++++++++++++++++++ src/common/extension.h | 7 +++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/application/application_manager.cc b/src/application/application_manager.cc index c79db024..9da4a0fc 100755 --- a/src/application/application_manager.cc +++ b/src/application/application_manager.cc @@ -453,7 +453,7 @@ void ApplicationManager::Launch(const picojson::value& args) { }; auto launch_response = [this](const std::shared_ptr& response) -> void { - this->instance_.PostMessage(response->serialize().c_str()); + Instance::PostMessage(&this->instance_, response->serialize().c_str()); }; TaskQueue::GetInstance().Queue(launch, launch_response, response); diff --git a/src/common/extension.cc b/src/common/extension.cc index 94ee3089..c11d5125 100755 --- a/src/common/extension.cc +++ b/src/common/extension.cc @@ -255,18 +255,39 @@ int32_t Extension::XW_Initialize(XW_Extension extension, return XW_OK; } +std::mutex Instance::instance_mutex_; +std::unordered_set Instance::all_instances_; Instance::Instance() : xw_instance_(0) { LoggerD("Enter"); + { + std::lock_guard lock(instance_mutex_); + all_instances_.insert(this); + } } Instance::~Instance() { LoggerD("Enter"); + { + std::lock_guard lock(instance_mutex_); + all_instances_.erase(this); + } Assert(xw_instance_ == 0); } +void Instance::PostMessage(Instance* that, const char* msg) { + LoggerD("Enter"); + std::lock_guard 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_) { diff --git a/src/common/extension.h b/src/common/extension.h index 7e67d2b4..3e65e8df 100755 --- a/src/common/extension.h +++ b/src/common/extension.h @@ -21,7 +21,9 @@ #include #include +#include #include +#include #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 all_instances_; + XW_Instance xw_instance_; }; -- 2.34.1