From: Lukasz Bardeli Date: Tue, 17 Oct 2017 09:38:26 +0000 (+0200) Subject: [Iotcon] fix to prevent crash. X-Git-Tag: submit/tizen_3.0/20171018.113206~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c6d55ff8e64eb3d091ea48f47bb1ef005406c42e;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [Iotcon] fix to prevent crash. Store data in vector and check in every call RemoteResourceResponseCallback if wasn't free earlier. [Verification] Code compiles without errors. TCT passrate 100% Change-Id: Ia3feb69460de99a0ad70915ae4b7098980fecb91 Signed-off-by: Lukasz Bardeli --- diff --git a/src/iotcon/iotcon_instance.cc b/src/iotcon/iotcon_instance.cc index 9b31a3ea..4996f1e6 100644 --- a/src/iotcon/iotcon_instance.cc +++ b/src/iotcon/iotcon_instance.cc @@ -16,7 +16,10 @@ #include "iotcon/iotcon_instance.h" +#include +#include #include +#include #include "common/logger.h" #include "common/scope_exit.h" @@ -37,6 +40,9 @@ const std::string kPrivilegeIotcon = "http://tizen.org/privilege/internet"; struct CallbackData { common::PostCallback fun; + CallbackData(common::PostCallback f) { + fun = f; + } }; struct CallbackData2 { @@ -48,6 +54,46 @@ long long GetId(const picojson::object& args) { return static_cast(args.find(kId)->second.get()); } +// CallbackDataManager was created to prevent crash that may occur when +// the same callback will be called twice in RemoteResourceResponseCallback +// (The native api allow that same callback will be called more than once) +class CallbackDataManager { + public: + static CallbackDataManager* GetInstance(); + void Add(CallbackData* data); + bool IfExists(CallbackData* data); + + private: + CallbackDataManager() {}; + CallbackDataManager(const CallbackDataManager &) = delete; + CallbackDataManager(const CallbackDataManager &&) = delete; + CallbackDataManager& operator=(const CallbackDataManager &) = delete; + CallbackDataManager& operator=(const CallbackDataManager &&) = delete; + ~CallbackDataManager() {}; + std::vector callback_; + std::mutex callback_mtx_; +}; + +CallbackDataManager* CallbackDataManager::GetInstance() { + ScopeLogger(); + static CallbackDataManager instance; + return &instance; +} + +void CallbackDataManager::Add(CallbackData* data) { + ScopeLogger(); + std::lock_guard lock(callback_mtx_); + callback_.push_back(data); +} + +bool CallbackDataManager::IfExists(CallbackData* data) { + ScopeLogger(); + std::lock_guard lock(callback_mtx_); + std::vector::iterator it; + it = find(callback_.begin(), callback_.end(), data); + return (it != callback_.end()); +} + void RemoteResourceResponseCallback(iotcon_remote_resource_h resource, iotcon_error_e err, iotcon_request_type_e request_type, iotcon_response_h response, void* user_data) { @@ -62,12 +108,31 @@ void RemoteResourceResponseCallback(iotcon_remote_resource_h resource, iotcon_er switch (err) { case IOTCON_ERROR_NONE: ret = IotconUtils::ResponseToJson(response, &value.get()); + if (CallbackDataManager::GetInstance()->IfExists(data.get())) { + LoggerD("user_data was called earlier, so ignore."); + data.release(); + return; + } break; case IOTCON_ERROR_TIMEOUT: - LoggerD("IOTCON_TIMEOUT "); + LoggerD("IOTCON_TIMEOUT"); + ret = IotconUtils::ConvertIotconError(err); + if (CallbackDataManager::GetInstance()->IfExists(data.get())) { + LoggerD("user_data was called earlier, so ignore."); + data.release(); + return; + } + break; default: ret = IotconUtils::ConvertIotconError(err); + if (CallbackDataManager::GetInstance()->IfExists(data.get())) { + LoggerD("user_data was called earlier, so ignore."); + data.release(); + return; + } + break; } + CallbackDataManager::GetInstance()->Add(data.get()); data->fun(ret, value); } else { LoggerE("Native callback data is null");