[Iotcon] fix to prevent crash. 89/155789/5
authorLukasz Bardeli <l.bardeli@samsung.com>
Tue, 17 Oct 2017 09:38:26 +0000 (11:38 +0200)
committerLukasz Bardeli <l.bardeli@samsung.com>
Tue, 17 Oct 2017 09:38:26 +0000 (11:38 +0200)
         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 <l.bardeli@samsung.com>
src/iotcon/iotcon_instance.cc

index 9b31a3ea22ef8e6929fb0901adb33f75f5555dbf..4996f1e6298f5ac5da85f74ae31ae70c18d5b15a 100644 (file)
 
 #include "iotcon/iotcon_instance.h"
 
+#include <algorithm>
+#include <mutex>
 #include <thread>
+#include <vector>
 
 #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<long long>(args.find(kId)->second.get<double>());
 }
 
+// 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<CallbackData*> callback_;
+  std::mutex callback_mtx_;
+};
+
+CallbackDataManager* CallbackDataManager::GetInstance() {
+  ScopeLogger();
+  static CallbackDataManager instance;
+  return &instance;
+}
+
+void CallbackDataManager::Add(CallbackData* data) {
+  ScopeLogger();
+  std::lock_guard<std::mutex> lock(callback_mtx_);
+  callback_.push_back(data);
+}
+
+bool CallbackDataManager::IfExists(CallbackData* data) {
+  ScopeLogger();
+  std::lock_guard<std::mutex> lock(callback_mtx_);
+  std::vector<CallbackData*>::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<picojson::object>());
+        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");