[Iotcon] fix for crash while finding resource 61/163161/1
authorLukasz Bardeli <l.bardeli@samsung.com>
Thu, 7 Dec 2017 12:09:10 +0000 (13:09 +0100)
committerLukasz Bardeli <l.bardeli@samsung.com>
Thu, 7 Dec 2017 12:09:10 +0000 (13:09 +0100)
Fix for crash when ResourceFoundCallback is called first time with TIMEOUT
and second time with proper value. Now data is deleted 10 seconds after
time when device stopped finding resources

[Verification] Code compiles without error. TCT tests 100% passrate

Change-Id: I3320a70dabddbbb1b5ff8fcc0161dbe1ffc23b95
Signed-off-by: Lukasz Bardeli <l.bardeli@samsung.com>
src/iotcon/iotcon_instance.cc

index 1ca926dd4d61f7d8a27177d143c83de1408a62d6..d6506992f68a7a78da376493a27bf2a41e7b00e4 100644 (file)
@@ -45,11 +45,6 @@ struct CallbackData {
   }
 };
 
-struct CallbackData2 {
-  common::PostCallback fun;
-  bool callback_called;
-};
-
 long long GetId(const picojson::object& args) {
   return static_cast<long long>(args.find(kId)->second.get<double>());
 }
@@ -110,7 +105,6 @@ void RemoteResourceResponseCallback(iotcon_remote_resource_h resource, iotcon_er
         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;
@@ -119,7 +113,6 @@ void RemoteResourceResponseCallback(iotcon_remote_resource_h resource, iotcon_er
         ret = IotconUtils::ConvertIotconError(err);
         if (CallbackDataManager::GetInstance()->IfExists(data.get())) {
           LoggerD("user_data was called earlier, so ignore.");
-          data.release();
           return;
         }
         break;
@@ -127,13 +120,13 @@ void RemoteResourceResponseCallback(iotcon_remote_resource_h resource, iotcon_er
         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);
+    data.release();
   } else {
     LoggerE("Native callback data is null");
   }
@@ -1302,38 +1295,28 @@ common::TizenResult IotconInstance::RemoteResourceSetTimeInterval(const picojson
 bool IotconInstance::ResourceFoundCallback(iotcon_remote_resource_h resource, iotcon_error_e result,
                                            void* user_data) {
   ScopeLogger();
-  CallbackData2* data = static_cast<CallbackData2*>(user_data);
+  CallbackData* data = static_cast<CallbackData*>(user_data);
   if (nullptr == data) {
     LoggerE("ResourceFoundCallback() failed.  Ignoring callback");
     return IOTCON_FUNC_STOP;
   }
 
+  picojson::value v{picojson::object{}};
+  common::TizenResult ret = common::TizenSuccess();
   switch (result) {
     case IOTCON_ERROR_NONE:
+      ret = IotconUtils::RemoteResourceToJson(resource, &v.get<picojson::object>());
       break;
     case IOTCON_ERROR_TIMEOUT:
-      LoggerD("IOTCON_TIMEOUT data->callback_called :%d", data->callback_called);
-      if (!data->callback_called) {
-        auto ret = IotconUtils::ConvertIotconError(result);
-        data->fun(ret, picojson::value{});
-      }
-      delete data;
-      return IOTCON_FUNC_STOP;
+      LoggerD("IOTCON_TIMEOUT");
     default:
-      auto ret = IotconUtils::ConvertIotconError(result);
-      data->fun(ret, picojson::value{});
-      return IOTCON_FUNC_STOP;
+      ret = IotconUtils::ConvertIotconError(result);
   }
 
-  picojson::value json_result = picojson::value(picojson::object());
-
-  auto ret = IotconUtils::RemoteResourceToJson(resource, &(json_result.get<picojson::object>()));
+  data->fun(ret, v);
   if (!ret) {
-    data->fun(ret, picojson::value{});
     return IOTCON_FUNC_STOP;
   }
-  data->callback_called = true;
-  data->fun(ret, json_result);
 
   return IOTCON_FUNC_CONTINUE;
 }
@@ -1386,9 +1369,7 @@ common::TizenResult IotconInstance::ClientFindResource(const picojson::object& a
     Post(kFindResourceListenerToken, common::TizenSuccess{response});
   };
 
-  CallbackData2* data = new CallbackData2{};
-  data->fun = response;
-  data->callback_called = false;
+  CallbackData* data = new CallbackData{response};
 
   LoggerD("Running find with:\nhost_address: %s,\nconnectivity_type: %d", host_address,
           connectivity_type);
@@ -1397,6 +1378,20 @@ common::TizenResult IotconInstance::ClientFindResource(const picojson::object& a
   if (!result) {
     delete data;
     LogAndReturnTizenError(result);
+  } else {
+    int timeout = 60; //default value set much bigger than default value for iotcon = 30s
+    auto result = IotconUtils::ConvertIotconError(iotcon_get_timeout(&timeout));
+    if (!result) {
+      LoggerE("iotcon_get_timeout - function call failed, using default value %d", timeout);
+    } else {
+      timeout = timeout + 10; //add 10 extra second to prevent too fast delete
+    }
+    // adding listener to delete data, when find would be finished
+    std::thread([data, timeout]() {
+      std::this_thread::sleep_for(std::chrono::seconds(timeout));
+      LoggerD("Deleting resource find data: %p", data);
+      delete data;
+    }).detach();
   }
 
   return common::TizenSuccess();
@@ -1471,7 +1466,7 @@ common::TizenResult IotconInstance::ClientRemovePresenceEventListener(
 bool IotconDeviceInfoCb(iotcon_device_info_h device_info, iotcon_error_e result, void* user_data) {
   ScopeLogger();
 
-  CallbackData2* data = static_cast<CallbackData2*>(user_data);
+  CallbackData* data = static_cast<CallbackData*>(user_data);
   if (nullptr == data) {
     LoggerE("IotconDeviceInfoCb() failed.  Ignoring callback");
     return IOTCON_FUNC_STOP;
@@ -1483,21 +1478,17 @@ bool IotconDeviceInfoCb(iotcon_device_info_h device_info, iotcon_error_e result,
   switch (result) {
     case IOTCON_ERROR_NONE:
       ret = IotconUtils::DeviceInfoToJson(device_info, &v.get<picojson::object>());
-      data->callback_called = true;
       break;
     case IOTCON_ERROR_TIMEOUT:
-      LoggerD("IOTCON_TIMEOUT data->callback_called :%d", data->callback_called);
-      if (!data->callback_called) {
-        ret = IotconUtils::ConvertIotconError(result);
-        data->fun(ret, v);
-      }
-      delete data;
-      return IOTCON_FUNC_STOP;
+      LoggerD("IOTCON_TIMEOUT");
     default:
       ret = IotconUtils::ConvertIotconError(result);
   }
 
   data->fun(ret, v);
+  if (!ret) {
+    return IOTCON_FUNC_STOP;
+  }
 
   return IOTCON_FUNC_CONTINUE;
 }
@@ -1550,9 +1541,7 @@ common::TizenResult IotconInstance::ClientFindDeviceInfo(const picojson::object&
     Post(kFindDeviceInfoListenerToken, common::TizenSuccess{response});
   };
 
-  CallbackData2* data = new CallbackData2{};
-  data->fun = response;
-  data->callback_called = false;
+  CallbackData* data = new CallbackData{response};
 
   auto result = IotconUtils::ConvertIotconError(
       iotcon_find_device_info(host_address, con_type_e, query, IotconDeviceInfoCb, data));
@@ -1560,6 +1549,20 @@ common::TizenResult IotconInstance::ClientFindDeviceInfo(const picojson::object&
   if (!result) {
     delete data;
     LogAndReturnTizenError(result);
+  } else {
+    int timeout = 60; //default value set much bigger than default value for iotcon = 30s
+    auto result = IotconUtils::ConvertIotconError(iotcon_get_timeout(&timeout));
+    if (!result) {
+      LoggerE("iotcon_get_timeout - function call failed, using default value %d", timeout);
+    } else {
+      timeout = timeout + 10; //add 10 extra second to prevent too fast delete
+    }
+    // adding listener to delete data, when find would be finished
+    std::thread([data, timeout]() {
+      std::this_thread::sleep_for(std::chrono::seconds(timeout));
+      LoggerD("Deleting resource find data: %p", data);
+      delete data;
+    }).detach();
   }
 
   return common::TizenSuccess();
@@ -1569,7 +1572,7 @@ bool IotconPlatformInfoCb(iotcon_platform_info_h platform_info, iotcon_error_e r
                           void* user_data) {
   ScopeLogger();
 
-  CallbackData2* data = static_cast<CallbackData2*>(user_data);
+  CallbackData* data = static_cast<CallbackData*>(user_data);
   if (nullptr == data) {
     LoggerE("IotconPlatformInfoCb() failed.  Ignoring callback");
     return IOTCON_FUNC_STOP;
@@ -1581,21 +1584,17 @@ bool IotconPlatformInfoCb(iotcon_platform_info_h platform_info, iotcon_error_e r
   switch (result) {
     case IOTCON_ERROR_NONE:
       ret = IotconUtils::PlatformInfoToJson(platform_info, &v.get<picojson::object>());
-      data->callback_called = true;
       break;
     case IOTCON_ERROR_TIMEOUT:
-      LoggerD("IOTCON_TIMEOUT data->callback_called :%d", data->callback_called);
-      if (!data->callback_called) {
-        ret = IotconUtils::ConvertIotconError(result);
-        data->fun(ret, v);
-      }
-      delete data;
-      return IOTCON_FUNC_STOP;
+      LoggerD("IOTCON_TIMEOUT");
     default:
       ret = IotconUtils::ConvertIotconError(result);
   }
 
   data->fun(ret, v);
+  if (!ret) {
+    return IOTCON_FUNC_STOP;
+  }
 
   return IOTCON_FUNC_CONTINUE;
 }
@@ -1648,9 +1647,7 @@ common::TizenResult IotconInstance::ClientFindPlatformInfo(const picojson::objec
     Post(kFindPlatformInfoListenerToken, common::TizenSuccess{response});
   };
 
-  CallbackData2* data = new CallbackData2{};
-  data->fun = response;
-  data->callback_called = false;
+  CallbackData* data = new CallbackData{response};
 
   auto result = IotconUtils::ConvertIotconError(
       iotcon_find_platform_info(host_address, con_type_e, query, IotconPlatformInfoCb, data));
@@ -1658,6 +1655,20 @@ common::TizenResult IotconInstance::ClientFindPlatformInfo(const picojson::objec
   if (!result) {
     delete data;
     LogAndReturnTizenError(result);
+  } else {
+    int timeout = 60; //default value set much bigger than default value for iotcon = 30s
+    auto result = IotconUtils::ConvertIotconError(iotcon_get_timeout(&timeout));
+    if (!result) {
+      LoggerE("iotcon_get_timeout - function call failed, using default value %d", timeout);
+    } else {
+      timeout = timeout + 10; //add 10 extra second to prevent too fast delete
+    }
+    // adding listener to delete data, when find would be finished
+    std::thread([data, timeout]() {
+      std::this_thread::sleep_for(std::chrono::seconds(timeout));
+      LoggerD("Deleting resource find data: %p", data);
+      delete data;
+    }).detach();
   }
 
   return common::TizenSuccess();