Fix toolkit_table destroy bug 32/125832/5
authorHyunho Kang <hhstark.kang@samsung.com>
Wed, 19 Apr 2017 05:05:53 +0000 (14:05 +0900)
committerHyunho Kang <hhstark.kang@samsung.com>
Fri, 21 Apr 2017 01:00:19 +0000 (10:00 +0900)
screen_connector_toolkit_evas_fini is called remote surface is destroyed
but screen_connector_toolkit_evas_h will not freed, so callback which have
a screen_connector_toolkit_evas_h as a user data like __rs_cb_mouse_move
callback could cause crash when they try to send event through already
destroyed remote surface

Change-Id: Ifda77fa1cb0244186179c7ffe2dc77b536593586
Signed-off-by: Hyunho Kang <hhstark.kang@samsung.com>
screen_connector_watcher_evas/src/screen_connector_toolkit_evas.c

index 7dc3cec..bf2585d 100644 (file)
@@ -34,6 +34,7 @@
 #endif
 
 #define LOG_TAG "SC_WATCHER_EVAS"
+#define SC_TOOLKIT_HANDLE_TAG "SC_TOOLKIT_HANDLE_TAG"
 
 struct _screen_connector_type_evas_h {
        GHashTable *toolkit_table;
@@ -70,6 +71,53 @@ static void __destroy_type_h(gpointer data)
        free(type_h);
 }
 
+static void __clear_img_tbm(screen_connector_toolkit_evas_h toolkit_evas_h)
+{
+       char *plug_id;
+
+       if (toolkit_evas_h->img_tbm == NULL)
+               return;
+
+       plug_id = evas_object_data_del(toolkit_evas_h->img_tbm, "___PLUGID");
+       if (plug_id)
+               free(plug_id);
+
+       evas_object_del(toolkit_evas_h->img_tbm);
+       toolkit_evas_h->img_tbm = NULL;
+}
+
+static void __clear_img_file(screen_connector_toolkit_evas_h toolkit_evas_h)
+{
+       if (toolkit_evas_h->img_file == NULL)
+               return;
+
+       evas_object_del(toolkit_evas_h->img_file);
+       toolkit_evas_h->img_file = NULL;
+}
+
+static void __destroy_toolkit_evas_h(gpointer data)
+{
+       char *plug_id;
+       screen_connector_toolkit_evas_h toolkit_evas_h = data;
+
+       if (!toolkit_evas_h)
+               return;
+
+       if (toolkit_evas_h->img_tbm != NULL) {
+               plug_id = evas_object_data_del(toolkit_evas_h->img_tbm, "___PLUGID");
+               if (plug_id)
+                       free(plug_id);
+       }
+
+       if (toolkit_evas_h->toolkit_h)
+               screen_connector_toolkit_remove(toolkit_evas_h->toolkit_h);
+
+       if (toolkit_evas_h->ops)
+               free(toolkit_evas_h->ops);
+
+       free(toolkit_evas_h);
+}
+
 EXPORT_API int screen_connector_toolkit_evas_init(Evas_Object *win, screen_connector_screen_type_e type)
 {
        screen_connector_type_evas_h type_h;
@@ -85,7 +133,7 @@ EXPORT_API int screen_connector_toolkit_evas_init(Evas_Object *win, screen_conne
                        return -1;
                }
 
-               type_h->toolkit_table = g_hash_table_new(g_direct_hash, g_direct_equal);
+               type_h->toolkit_table = g_hash_table_new_full(g_str_hash, g_str_equal, free, __destroy_toolkit_evas_h);
                if (!type_h->toolkit_table) {
                        LOGE("failed to create table");
                        free(type_h);
@@ -124,7 +172,7 @@ EXPORT_API int screen_connector_toolkit_evas_fini(screen_connector_screen_type_e
        return screen_connector_toolkit_fini(type);
 }
 
-static bool __obj_is_visible(Evas_Object *obj, screen_connector_toolkit_evas_h toolkit_evas_h)
+static bool __obj_is_visible(screen_connector_toolkit_evas_h toolkit_evas_h)
 {
        int x, y, w, h;
        Ecore_Wl_Window *window = NULL;
@@ -136,9 +184,14 @@ static bool __obj_is_visible(Evas_Object *obj, screen_connector_toolkit_evas_h t
                return false;
        }
 
+       if (toolkit_evas_h->img_tbm == NULL) {
+               LOGE("img_tbm is NULL");
+               return false;
+       }
+
        window = elm_win_wl_window_get(toolkit_evas_h->type_h->viewer_win);
        ecore_wl_window_geometry_get(window, &window_x, &window_y, &window_w, &window_h);
-       evas_object_geometry_get(obj, &x, &y, &w, &h);
+       evas_object_geometry_get(toolkit_evas_h->img_tbm, &x, &y, &w, &h);
        rotation = ecore_wl_window_rotation_get(window);
 
        if (x >= 0 && x < window_w &&
@@ -196,7 +249,7 @@ static void __obj_update_visibility(void *data, Evas *e, Evas_Object *obj, void
                return;
        }
 
-       if (__obj_is_visible(obj, toolkit_evas_h))
+       if (__obj_is_visible(toolkit_evas_h))
                __set_visibility(toolkit_evas_h, VISIBILITY_TYPE_UNOBSCURED);
        else
                __set_visibility(toolkit_evas_h, VISIBILITY_TYPE_FULLY_OBSCURED);
@@ -390,25 +443,6 @@ static void __rs_cb_resize(void *data, Evas *e, Evas_Object *obj, void *event_in
        __obj_update_visibility(data, e, obj, event_info);
 }
 
-static void __clear_img_tbm(screen_connector_toolkit_evas_h toolkit_evas_h)
-{
-       if (toolkit_evas_h->img_tbm == NULL)
-               return;
-
-       g_hash_table_remove(toolkit_evas_h->type_h->toolkit_table, toolkit_evas_h->img_tbm);
-       evas_object_del(toolkit_evas_h->img_tbm);
-       toolkit_evas_h->img_tbm = NULL;
-}
-
-static void __clear_img_file(screen_connector_toolkit_evas_h toolkit_evas_h)
-{
-       if (toolkit_evas_h->img_file == NULL)
-               return;
-
-       evas_object_del(toolkit_evas_h->img_file);
-       toolkit_evas_h->img_file = NULL;
-}
-
 static void __toolkit_update_cb(struct tizen_remote_surface *trs, uint32_t type, struct wl_buffer *tbm,
                int32_t img_file_fd, uint32_t img_file_size, uint32_t time, struct wl_array *keys,
                const char *appid, const char *instance_id, const int pid, void *data)
@@ -455,11 +489,13 @@ static void __toolkit_update_cb(struct tizen_remote_surface *trs, uint32_t type,
                                __rs_cb_resize, toolkit_evas_h);
 
                /* Store toolkit_evas_h */
-               g_hash_table_insert(toolkit_evas_h->type_h->toolkit_table, toolkit_evas_h->img_tbm, toolkit_evas_h);
+               g_hash_table_insert(toolkit_evas_h->type_h->toolkit_table, strdup(instance_id), toolkit_evas_h);
 
                /* Set data to use in accessibility */
                snprintf(plug_id, sizeof(plug_id), "%s:%d", instance_id, pid);
                evas_object_data_set(toolkit_evas_h->img_tbm, "___PLUGID", strdup(plug_id));
+
+               evas_object_data_set(toolkit_evas_h->img_tbm, SC_TOOLKIT_HANDLE_TAG, toolkit_evas_h);
                evas_object_event_callback_add(toolkit_evas_h->img_tbm,
                                EVAS_CALLBACK_MOVE, __obj_update_visibility, toolkit_evas_h);
        }
@@ -538,25 +574,6 @@ static void __toolkit_added_cb(const char *appid, const char *instance_id, const
 {
 }
 
-static void __free_toolkit_evas_h(screen_connector_toolkit_evas_h toolkit_evas_h)
-{
-       if (!toolkit_evas_h)
-               return;
-
-       if (toolkit_evas_h->toolkit_h)
-               screen_connector_toolkit_remove(toolkit_evas_h->toolkit_h);
-
-       __clear_img_file(toolkit_evas_h);
-       __clear_img_tbm(toolkit_evas_h);
-
-       if (toolkit_evas_h->ops) {
-               free(toolkit_evas_h->ops);
-               toolkit_evas_h->ops = NULL;
-       }
-
-       free(toolkit_evas_h);
-}
-
 static void __toolkit_removed_cb(const char *appid, const char *instance_id, const int pid, void *data)
 {
        screen_connector_toolkit_evas_h toolkit_evas_h;
@@ -569,20 +586,18 @@ static void __toolkit_removed_cb(const char *appid, const char *instance_id, con
                return;
        }
 
-       if (toolkit_evas_h->type_h->toolkit_table != NULL && toolkit_evas_h->img_tbm != NULL) {
-               g_hash_table_remove(toolkit_evas_h->type_h->toolkit_table, toolkit_evas_h->img_tbm);
-
-               /* Remove data used in accessibility */
+       if (toolkit_evas_h->img_tbm != NULL) {
                plug_id = evas_object_data_del(toolkit_evas_h->img_tbm, "___PLUGID");
-               free(plug_id);
-       }
+               if (plug_id)
+                       free(plug_id);
 
-       if (toolkit_evas_h->img_tbm != NULL)
+               evas_object_data_del(toolkit_evas_h->img_tbm, SC_TOOLKIT_HANDLE_TAG);
                toolkit_evas_h->ops->removed_cb(appid, instance_id, pid, toolkit_evas_h->img_tbm, toolkit_evas_h->data);
-       else if (toolkit_evas_h->img_file != NULL)
+       } else if (toolkit_evas_h->img_file != NULL) {
                toolkit_evas_h->ops->removed_cb(appid, instance_id, pid, toolkit_evas_h->img_file, toolkit_evas_h->data);
+       }
 
-       __free_toolkit_evas_h(toolkit_evas_h);
+       g_hash_table_remove(toolkit_evas_h->type_h->toolkit_table, instance_id);
 }
 
 EXPORT_API screen_connector_toolkit_evas_h screen_connector_toolkit_evas_add(screen_connector_toolkit_evas_ops *ops, char *id,
@@ -628,10 +643,18 @@ EXPORT_API screen_connector_toolkit_evas_h screen_connector_toolkit_evas_add(scr
 
 EXPORT_API int screen_connector_toolkit_evas_remove(screen_connector_toolkit_evas_h handle)
 {
+       const char *instance_id;
+
        if (handle == NULL)
                return -1;
 
-       __free_toolkit_evas_h(handle);
+       instance_id = screen_connector_toolkit_get_instance_id(handle->toolkit_h);
+       if (instance_id == NULL) {
+               LOGE("Null instance_id");
+               return -1;
+       }
+       g_hash_table_remove(handle->type_h->toolkit_table, instance_id);
+
        return 0;
 }
 
@@ -643,7 +666,6 @@ EXPORT_API int screen_connector_toolkit_evas_update(const char *appid, const cha
 static void __send_visibility(gpointer key, gpointer value, gpointer user_data)
 {
        screen_connector_toolkit_evas_h toolkit_evas_h = (screen_connector_toolkit_evas_h)value;
-       Evas_Object *evas_obj = (Evas_Object *)key;
        unsigned int event = GPOINTER_TO_INT(user_data);
        int ret;
        visibility_type type;
@@ -651,7 +673,7 @@ static void __send_visibility(gpointer key, gpointer value, gpointer user_data)
        if (toolkit_evas_h->freeze)
                return;
 
-       if (!__obj_is_visible(evas_obj, toolkit_evas_h))
+       if (!__obj_is_visible(toolkit_evas_h))
                return;
 
        if (event)
@@ -661,7 +683,7 @@ static void __send_visibility(gpointer key, gpointer value, gpointer user_data)
 
        ret = __set_visibility(toolkit_evas_h, type);
        if (ret == -1)
-               LOGE("failed to set object visibility  set %p to %d", evas_obj, type);
+               LOGE("failed to set object visibility  set %p to %d", toolkit_evas_h->img_tbm, type);
 }
 
 static Eina_Bool __visibility_cb(void *data, int type, void *event)
@@ -712,21 +734,10 @@ EXPORT_API int screen_connector_toolkit_evas_stop_visibility_notify(void)
 screen_connector_toolkit_evas_h __find_toolkit_evas_h(Evas_Object *obj)
 {
        screen_connector_toolkit_evas_h toolkit_evas_h;
-       GHashTableIter iter;
-       gpointer key, value;
-       screen_connector_type_evas_h cur_type;
 
-       g_hash_table_iter_init(&iter, __type_table);
-       while (g_hash_table_iter_next(&iter, &key, &value)) {
-               cur_type = (screen_connector_type_evas_h)value;
-               if (cur_type->toolkit_table) {
-                       toolkit_evas_h = g_hash_table_lookup(cur_type->toolkit_table, obj);
-                       if (toolkit_evas_h != NULL)
-                               return toolkit_evas_h;
-               }
-       }
+       toolkit_evas_h = evas_object_data_get(obj, SC_TOOLKIT_HANDLE_TAG);
 
-       return NULL;
+       return toolkit_evas_h;
 }
 
 EXPORT_API int screen_connector_toolkit_evas_freeze_visibility(Evas_Object *obj, visibility_type type)