Adds mutex for data_changed_cb 24/234924/5
authorInkyun Kil <inkyun.kil@samsung.com>
Mon, 1 Jun 2020 00:57:22 +0000 (09:57 +0900)
committerInkyun Kil <inkyun.kil@samsung.com>
Tue, 23 Jun 2020 06:34:01 +0000 (15:34 +0900)
The value of __changed_provider_list can be used simultaneously on
data_control_add_data_changed_cb and data_control_remove_data_changed_cb

Change-Id: I05e86f9b451b0cb89f1d2a3cbdef9ba634da7fbf
Signed-off-by: Inkyun Kil <inkyun.kil@samsung.com>
src/data_control_internal.c
src/data_control_internal.h
src/data_control_noti.c

index 364f80e..d426ba6 100644 (file)
@@ -100,6 +100,8 @@ static GHashTable *__checked_consumer_hash;
 
 static GDBusConnection *_gdbus_conn;
 
+static pthread_mutex_t __data_control_mutex = PTHREAD_MUTEX_INITIALIZER;
+
 /* 100 milliseconds */
 const struct timespec TRY_SLEEP_TIME = { 0, 100 * 1000 * 1000 };
 
@@ -2416,3 +2418,13 @@ int _get_handle_id(data_control_h provider, int *handle_id)
 
        return DATA_CONTROL_ERROR_NONE;
 }
+
+void _data_control_lock_mutex()
+{
+       pthread_mutex_lock(&__data_control_mutex);
+}
+
+void _data_control_unlock_mutex()
+{
+       pthread_mutex_unlock(&__data_control_mutex);
+}
index 43d0933..115e9a5 100644 (file)
@@ -197,5 +197,7 @@ int _unregister_response_cb(data_control_h provider, bool is_bind,
 int _request_provider(data_control_h provider, datacontrol_request_type type,
                bundle *request_data, void *extra_data, int request_id);
 
+void _data_control_lock_mutex();
+void _data_control_unlock_mutex();
 #endif /* _APPFW_DATA_CONTROL_INTERNAL_H_ */
 
index 2e22c5b..0d9bee8 100644 (file)
@@ -98,6 +98,22 @@ static void __free_provider_info(
        }
 }
 
+static gpointer __g_copy_func(gconstpointer src, gpointer data)
+{
+       changed_cb_info_s *src_cb_info = (changed_cb_info_s*)src;
+       changed_cb_info_s *cb_info =
+                       (changed_cb_info_s *)calloc(1, sizeof(changed_cb_info_s));
+       if (cb_info == NULL) {
+               _LOGE("changed_cb_info_s alloc fail out of memory.");
+       } else {
+               cb_info->changed_cb = src_cb_info->changed_cb;
+               cb_info->user_data = src_cb_info->user_data;
+               cb_info->callback_id = src_cb_info->callback_id;
+       }
+
+       return (gpointer)cb_info;
+}
+
 static void __noti_process(GVariant *parameters)
 {
        char *provider_id = NULL;
@@ -111,6 +127,7 @@ static void __noti_process(GVariant *parameters)
        provider_info_s find_info;
        provider_info_s *provider_info;
        GList *callback_list = NULL;
+       GList *copied_callback_list = NULL;
        data_control_data_change_type_e type;
 
        g_variant_get(parameters, "(i&s&s&si)",
@@ -123,26 +140,33 @@ static void __noti_process(GVariant *parameters)
        find_info.provider_id = provider_id;
        find_info.data_id = data_id;
 
+       _data_control_lock_mutex();
+
        find_list = g_list_find_custom(__changed_provider_list, &find_info,
                        (GCompareFunc)__provider_info_compare_cb);
        if (find_list != NULL) {
+               provider_info = (provider_info_s *)find_list->data;
+               copied_callback_list =
+                               g_list_copy_deep(provider_info->cb_list, __g_copy_func, NULL);
+               _data_control_unlock_mutex();
+
                _create_data_control_h(&provider);
                _set_provider_id(provider, provider_id);
                _set_data_id(provider, data_id);
                noti_data = bundle_decode(raw, len);
-               provider_info = (provider_info_s *)find_list->data;
-               callback_list = g_list_first(provider_info->cb_list);
+               callback_list = g_list_first(copied_callback_list);
                for (; callback_list != NULL; callback_list = callback_list->next) {
                        cb_info = callback_list->data;
                        cb_info->changed_cb((data_control_h)provider,
                                        type, noti_data, cb_info->user_data);
                        _LOGI("callback called: %s, %s",
-                                       provider_info->provider_id, provider_info->data_id);
+                                       find_info.provider_id, find_info.data_id);
                }
                bundle_free(noti_data);
                _destroy_data_control_h(provider, false);
-
+               g_list_free_full(copied_callback_list, free);
        } else {
+               _data_control_unlock_mutex();
                _LOGE("data_control_data_change_cb is null");
        }
        _LOGI("__noti_process done");
@@ -151,37 +175,50 @@ static void __noti_process(GVariant *parameters)
 static void __call_result_callback(int callback_id, int callback_result)
 {
        add_callback_result_cb_info_s *result_cb_info;
+       add_callback_result_cb_info_s copied_result_cb_info;
        add_callback_result_cb_info_s find_info;
        data_control_h provider;
        GList *find_list;
 
+       _data_control_lock_mutex();
+
        find_info.callback_id = callback_id;
        find_list = g_list_find_custom(__add_callback_result_cb_list, &find_info,
                        (GCompareFunc)__callback_result_info_compare_cb);
 
        if (find_list != NULL) {
                result_cb_info = (add_callback_result_cb_info_s *)find_list->data;
-               if (result_cb_info->callback) {
+               copied_result_cb_info.provider_id = strdup(result_cb_info->provider_id);
+               copied_result_cb_info.data_id = strdup(result_cb_info->data_id);
+               copied_result_cb_info.callback = result_cb_info->callback;
+               copied_result_cb_info.user_data = result_cb_info->user_data;
+               _data_control_unlock_mutex();
+               if (copied_result_cb_info.callback) {
                        _create_data_control_h(&provider);
-                       _set_provider_id(provider, result_cb_info->provider_id);
-                       _set_data_id(provider, result_cb_info->data_id);
+                       _set_provider_id(provider, copied_result_cb_info.provider_id);
+                       _set_data_id(provider, copied_result_cb_info.data_id);
 
-                       result_cb_info->callback(
+                       copied_result_cb_info.callback(
                                        (data_control_h)provider,
                                        callback_result,
                                        callback_id,
-                                       result_cb_info->user_data);
+                                       copied_result_cb_info.user_data);
 
                        _destroy_data_control_h(provider, false);
                } else {
                        _LOGE("data_control_add_callback_result_cb is null");
                }
+               if (copied_result_cb_info.provider_id)
+                       free(copied_result_cb_info.provider_id);
+               if (copied_result_cb_info.data_id)
+                       free(copied_result_cb_info.data_id);
 
                __add_callback_result_cb_list =
                        g_list_remove(__add_callback_result_cb_list, find_list->data);
                __free_result_cb_info(result_cb_info);
        } else {
                _LOGE("add_callback_result_cb_info_s is null");
+               _data_control_unlock_mutex();
        }
 }
 
@@ -189,10 +226,8 @@ static void __call_result_callback(int callback_id, int callback_result)
 static gboolean __add_callback_result_timeout_handler(gpointer user_data)
 {
        _LOGE("add data changed callback time out !!!");
-       add_callback_result_cb_info_s *result_cb_info =
-                       (add_callback_result_cb_info_s *)user_data;
-       __call_result_callback(result_cb_info->callback_id,
-                       DATA_CONTROL_ERROR_IO_ERROR);
+       gint callback_id = GPOINTER_TO_INT(user_data);
+       __call_result_callback(callback_id, DATA_CONTROL_ERROR_IO_ERROR);
        return FALSE;
 }
 /* LCOV_EXCL_STOP */
@@ -342,6 +377,8 @@ EXPORT_API int data_control_add_data_change_cb(
        unique_id = g_dbus_connection_get_unique_name(_get_dbus_connection());
        _LOGI("unique_id : %s, callback_id %d", unique_id, data_changed_callback_id);
 
+       _data_control_lock_mutex();
+
        find_provider_info.provider_id = provider->provider_id;
        find_provider_info.data_id = provider->data_id;
        find_list = g_list_find_custom(__changed_provider_list, &find_provider_info,
@@ -458,7 +495,8 @@ EXPORT_API int data_control_add_data_change_cb(
        *callback_id = data_changed_callback_id;
 
        result_cb_info->timeout_id =
-               g_timeout_add(5000, __add_callback_result_timeout_handler, result_cb_info);
+               g_timeout_add(5000, __add_callback_result_timeout_handler,
+               GINT_TO_POINTER(data_changed_callback_id));
        __add_callback_result_cb_list =
                g_list_append(__add_callback_result_cb_list, result_cb_info);
        _LOGI("datacontrol_add_data_change_cb done");
@@ -482,6 +520,7 @@ err:
                        __free_result_cb_info(result_cb_info);
        }
 
+       _data_control_unlock_mutex();
        return ret;
        /* LCOV_EXCL_STOP */
 }
@@ -515,14 +554,19 @@ EXPORT_API int data_control_remove_data_change_cb(data_control_h provider,
                        return DATA_CONTROL_ERROR_PERMISSION_DENIED;
        }
 
+       ret = DATA_CONTROL_ERROR_NONE;
+
        info.provider_id = provider->provider_id;
        info.data_id = provider->data_id;
 
+       _data_control_lock_mutex();
+
        provider_list = g_list_find_custom(__changed_provider_list, &info,
                        (GCompareFunc)__provider_info_compare_cb);
        if (provider_list == NULL) {
                _LOGE("Cannot find provider info");
-               return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+               ret = DATA_CONTROL_ERROR_INVALID_PARAMETER;
+               goto err;
        }
 
        cb_info.callback_id = callback_id;
@@ -533,7 +577,8 @@ EXPORT_API int data_control_remove_data_change_cb(data_control_h provider,
                        (GCompareFunc)__changed_cb_info_compare_cb);
        if (callback_list == NULL) {
                _LOGE("Cannot find changed callback info");
-               return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+               ret = DATA_CONTROL_ERROR_INVALID_PARAMETER;
+               goto err;
        }
 
        removed_cb_info = (changed_cb_info_s *)callback_list->data;
@@ -553,7 +598,7 @@ EXPORT_API int data_control_remove_data_change_cb(data_control_h provider,
                                        DATACONTROL_TYPE_REMOVE_DATA_CHANGED_CB);
                if (ret != DATA_CONTROL_ERROR_NONE) {
                        _LOGE("__sql_request_provider fail %d", ret);
-                       return ret;
+                       goto err;
                }
 
                __changed_provider_list =
@@ -571,5 +616,8 @@ EXPORT_API int data_control_remove_data_change_cb(data_control_h provider,
                        g_list_remove(__add_callback_result_cb_list, result_cb_list->data);
                __free_result_cb_info(tmp);
        }
-       return DATA_CONTROL_ERROR_NONE;
+
+err:
+       _data_control_unlock_mutex();
+       return ret;
 }