From: Rafal Walczyna Date: Thu, 16 Nov 2017 06:52:50 +0000 (+0100) Subject: [DataControl] Crash when changeListener was not removed properly fixed X-Git-Tag: submit/tizen_4.0/20171117.110318~2^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=39d33809015fcd197d7fcab562ba27bef761806d;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [DataControl] Crash when changeListener was not removed properly fixed [Verification] Passrate 100% Change-Id: Ie9e5fd96a215a30e2ff53d9bfb4b9ed8a16406a8 Signed-off-by: Rafal Walczyna --- diff --git a/src/datacontrol/datacontrol_api.js b/src/datacontrol/datacontrol_api.js index 401be5c1..24a78c6e 100755 --- a/src/datacontrol/datacontrol_api.js +++ b/src/datacontrol/datacontrol_api.js @@ -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} ]); diff --git a/src/datacontrol/datacontrol_instance.cc b/src/datacontrol/datacontrol_instance.cc index 0c6ff0ab..cb1b6574 100644 --- a/src/datacontrol/datacontrol_instance.cc +++ b/src/datacontrol/datacontrol_instance.cc @@ -65,6 +65,19 @@ struct DatacontrolInformation { static std::map 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(args.get("callbackId").get()); int result = DATA_CONTROL_ERROR_NONE; data_control_h handle = nullptr; - std::function 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::type, decltype(deleter)> handle_ptr(handle, - deleter); - - std::shared_ptr 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 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(); - const std::string& dataId = args.get("dataId").get(); - const std::string& type = args.get("type").get(); int watch_id = static_cast(args.get("watchId").get()); - data_control_h handle = nullptr; - std::function 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::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 diff --git a/src/datacontrol/datacontrol_instance.h b/src/datacontrol/datacontrol_instance.h index 3478e973..2412774f 100644 --- a/src/datacontrol/datacontrol_instance.h +++ b/src/datacontrol/datacontrol_instance.h @@ -33,6 +33,9 @@ struct ReplyCallbackData { DatacontrolInstance* _instance; int callbackId; std::string event_type; + data_control_h handle; + + ~ReplyCallbackData(); }; typedef std::shared_ptr ReplyCallbackDataPtr;