[DataControl] Crash when changeListener was not removed properly fixed 42/160442/4
authorRafal Walczyna <r.walczyna@partner.samsung.com>
Thu, 16 Nov 2017 06:52:50 +0000 (07:52 +0100)
committerRafal Walczyna <r.walczyna@partner.samsung.com>
Thu, 16 Nov 2017 14:13:17 +0000 (15:13 +0100)
[Verification] Passrate 100%

Change-Id: Ie9e5fd96a215a30e2ff53d9bfb4b9ed8a16406a8
Signed-off-by: Rafal Walczyna <r.walczyna@partner.samsung.com>
src/datacontrol/datacontrol_api.js
src/datacontrol/datacontrol_instance.cc
src/datacontrol/datacontrol_instance.h

index 401be5c1e017731dc9cee13ac92ed8ca653ebc1a..24a78c6e71400cc972a5b0445b4c5f49c8ef2a69 100755 (executable)
@@ -105,7 +105,7 @@ var DataControlListenersManager = (function() {
           dataId: dataId,
           type: type
         }, callback);
-
+      result = native_.getResultObject(result);
       if (native_.isFailure(result)) {
         throw native_.getErrorObject(result);
       } else {
@@ -161,10 +161,7 @@ var DataControlListenersManager = (function() {
 
     if (0 != _realWatchId) {
       native_.call('DataControlConsumerObject_removeChangeListener',{
-        providerId: providerId,
-        dataId: dataId,
         watchId: _realWatchId,
-        type: type
       });
 
       if (type_.isEmptyObject(this._SQLDataControlCbMap) &&
@@ -238,7 +235,6 @@ DataControlConsumerObject.prototype.addChangeListener = function() {
 };
 
 DataControlConsumerObject.prototype.removeChangeListener = function() {
-
   var args = validator_.validateArgs(arguments, [
     {'name': 'watchId', 'type': types_.LONG}
   ]);
index 0c6ff0ab59d5339e0c1e031ec7773aaa8d5b3759..cb1b657461c4a5eaf89951247e98661352803e6a 100644 (file)
@@ -65,6 +65,19 @@ struct DatacontrolInformation {
 
 static std::map<int, DatacontrolInformation*> IdMap;
 
+ReplyCallbackData::~ReplyCallbackData() {
+  ScopeLogger();
+  if (SQL == event_type) {
+    if (handle && DATA_CONTROL_ERROR_NONE != data_control_sql_destroy(handle)) {
+      LoggerE("Destroy SQL handle failed");
+    }
+  } else {
+    if (handle && DATA_CONTROL_ERROR_NONE != data_control_map_destroy(handle)) {
+      LoggerE("Destroy MAP handle failed");
+    }
+  }
+}
+
 DatacontrolInstance::DatacontrolInstance() {
   ScopeLogger();
   using std::placeholders::_1;
@@ -91,6 +104,17 @@ DatacontrolInstance::DatacontrolInstance() {
 
 DatacontrolInstance::~DatacontrolInstance() {
   ScopeLogger();
+  for (auto& item : reply_map) {
+    int watch_id = item.first;
+    auto handle = item.second->handle;
+    LoggerD("Deleting callback number %d", item.first);
+    int result = ::data_control_remove_data_change_cb(handle, watch_id);
+    if (DATA_CONTROL_ERROR_NONE != result) {
+      LoggerE("RemoveChangeListener %d failed: %d (%s)", watch_id, result,
+              get_error_message(result));
+    }
+  }
+  reply_map.clear();
 }
 
 static void ReplyAsync(DatacontrolInstance* instance, int callbackId, bool isSuccess,
@@ -1088,36 +1112,25 @@ void DatacontrolInstance::AddChangeListener(const picojson::value& args, picojso
   int callbackId = static_cast<int>(args.get("callbackId").get<double>());
   int result = DATA_CONTROL_ERROR_NONE;
   data_control_h handle = nullptr;
-  std::function<int(data_control_h)> del;
 
   if (SQL == type) {
     result = CreateSQLHandle(providerId, dataId, &handle);
-    del = data_control_sql_destroy;
   } else {
     result = CreateMAPHandle(providerId, dataId, &handle);
-    del = data_control_map_destroy;
   }
 
-  auto deleter = [&del](data_control_h handle) {
-    if (handle && DATA_CONTROL_ERROR_NONE != del(handle)) {
-      LoggerE("Destroy handle failed");
-    }
-  };
-
-  std::unique_ptr<std::remove_pointer<data_control_h>::type, decltype(deleter)> handle_ptr(handle,
-                                                                                           deleter);
-
-  std::shared_ptr<ReplyCallbackData> user_data(new ReplyCallbackData());
-  user_data->_instance = this;
-  user_data->callbackId = callbackId;
-  user_data->event_type = type;
-
   if (DATA_CONTROL_ERROR_NONE != result) {
     LogAndReportError(ServiceNotAvailableException("AddChangeListener failed"), out,
                       ("AddChangeListener failed: %d (%s)", result, get_error_message(result)));
     return;
   }
 
+  std::shared_ptr<ReplyCallbackData> user_data(new ReplyCallbackData());
+  user_data->_instance = this;
+  user_data->callbackId = callbackId;
+  user_data->event_type = type;
+  user_data->handle = handle;
+
   int watch_id = 0;
   result = ::data_control_add_data_change_cb(handle, callback, user_data.get(), result_callback,
                                              user_data.get(), &watch_id);
@@ -1143,45 +1156,17 @@ void DatacontrolInstance::RemoveChangeListener(const picojson::value& args, pico
   CHECK_PRIVILEGE_ACCESS(kPrivilegeDatasharing, &out);
   CHECK_PRIVILEGE_ACCESS(kPrivilegeAppmanagerLaunch, &out);
 
-  CHECK_EXIST(args, "providerId", out)
-  CHECK_EXIST(args, "dataId", out)
   CHECK_EXIST(args, "watchId", out)
-  CHECK_EXIST(args, "type", out)
 
-  const std::string& providerId = args.get("providerId").get<std::string>();
-  const std::string& dataId = args.get("dataId").get<std::string>();
-  const std::string& type = args.get("type").get<std::string>();
   int watch_id = static_cast<int>(args.get("watchId").get<double>());
-  data_control_h handle = nullptr;
-  std::function<int(data_control_h)> del;
-  int result = DATA_CONTROL_ERROR_NONE;
-
-  if (SQL == type) {
-    result = CreateSQLHandle(providerId, dataId, &handle);
-    del = data_control_sql_destroy;
-  } else {
-    result = CreateMAPHandle(providerId, dataId, &handle);
-    del = data_control_map_destroy;
-  }
-
-  if (DATA_CONTROL_ERROR_NONE != result) {
-    // According to native documentation only IOError can be returned to webapi, other errors are
-    // handled earlier
+  if (reply_map.end() == reply_map.find(watch_id)) {
     LogAndReportError(IOException("RemoveChangeListener failed"), out,
-                      ("RemoveChangeListener failed: %d (%s)", result, get_error_message(result)));
+                      ("RemoveChangeListener failed, watch_id: %d", watch_id));
     return;
   }
+  data_control_h handle = reply_map[watch_id]->handle;
 
-  auto deleter = [&del](data_control_h handle) {
-    if (handle && DATA_CONTROL_ERROR_NONE != del(handle)) {
-      LoggerE("Destroy handle failed");
-    }
-  };
-
-  std::unique_ptr<std::remove_pointer<data_control_h>::type, decltype(deleter)> handle_ptr(handle,
-                                                                                           deleter);
-
-  result = ::data_control_remove_data_change_cb(handle, watch_id);
+  int result = ::data_control_remove_data_change_cb(handle, watch_id);
 
   if (DATA_CONTROL_ERROR_NONE != result) {
     // According to native documentation only IOError can be returned to webapi, other errors are
index 3478e973e42b4b9c765acc349dec43a38c8a2083..2412774f202225ca9fdddf211548794cea283214 100644 (file)
@@ -33,6 +33,9 @@ struct ReplyCallbackData {
   DatacontrolInstance* _instance;
   int callbackId;
   std::string event_type;
+  data_control_h handle;
+
+  ~ReplyCallbackData();
 };
 
 typedef std::shared_ptr<ReplyCallbackData> ReplyCallbackDataPtr;