e_pixmap: manage deleted pixmap hash table for some pixmaps that will be freed soon 41/44541/5 accepted/tizen/mobile/20150723.121324 accepted/tizen/tv/20150723.121344 accepted/tizen/wearable/20150723.121407 submit/tizen/20150723.044444
authorMinJeong Kim <minjjj.kim@samsung.com>
Thu, 23 Jul 2015 05:43:35 +0000 (14:43 +0900)
committerMinJeong Kim <minjjj.kim@samsung.com>
Thu, 23 Jul 2015 06:53:35 +0000 (15:53 +0900)
when enlightenment try to create new e_pixmap, e_pixmap hash table is checked
first with surface resource id as a hash key. if there is a pixmap data that
was registered by given key, e_pixmap is NOT newly created but its reference
count is just increased.

This mechanism can generate problem when more than two successive surface
resources are allocated same address. enlightenment have delayed free of e_pixmap
because there are a lot of thing to do before the pixmap is freed. so interval
between removal of a e_pixmap for previous surface resource and creation of
e_pixmap for next surface resource can be made. When the interval is
made and latest surface resource is allocated same address with previous
surface resource, latest surface resource fails to create new e_pixmap
and it will use e_pixmap for previous surface and it can cause abuse of
memory.

To fix this problem, hash table for deleted pixmap is newly added.

Change-Id: I54ead4101210e3dda75d03d18a1e3e840dd8813b
Signed-off-by: MinJeong Kim <minjjj.kim@samsung.com>
src/bin/e_comp_wl.c
src/bin/e_comp_wl_input.c
src/bin/e_pixmap.c
src/bin/e_pixmap.h
src/bin/e_win.c

index bd2545d2dbfd8b2277e41e6775ae1548f8932625..e249a26035d9c6648dd31f9322ab59fbc47d6471 100644 (file)
@@ -1828,6 +1828,8 @@ _e_comp_wl_surface_destroy(struct wl_resource *resource)
         e_pixmap_free(ep);
         return;
      }
+   else
+     e_pixmap_del(ep);
 
    evas_object_hide(ec->frame);
    e_object_del(E_OBJECT(ec));
@@ -1861,8 +1863,21 @@ _e_comp_wl_compositor_cb_surface_create(struct wl_client *client, struct wl_reso
                                   _e_comp_wl_surface_destroy);
 
    wl_client_get_credentials(client, &pid, NULL, NULL);
-   if (pid == getpid()) //internal!
-     ep = e_pixmap_find(E_PIXMAP_TYPE_WL, (uintptr_t)id);
+   if (pid == getpid())
+     {
+        /* pixmap of internal win was supposed to be created at trap show */
+        ep = e_pixmap_find(E_PIXMAP_TYPE_WL, (uintptr_t)id);
+     }
+   else
+     {
+        if ((ep = e_pixmap_find(E_PIXMAP_TYPE_WL, (uintptr_t)res)))
+          {
+             ERR("There is e_pixmap already, Delete old e_pixmap %p", ep);
+             e_pixmap_del(ep);
+             ep = NULL;
+          }
+     }
+
    if (!ep)
      {
         /* try to create new pixmap */
index fcbcd96da3165cf292aecc810d1f8274b6ce6809..a165ba0d076db82cf8abd54a1fb663e0f537b12f 100644 (file)
@@ -78,8 +78,13 @@ _e_comp_wl_input_pointer_cb_cursor_set(struct wl_client *client, struct wl_resou
    if (!(ec = e_pixmap_find_client(E_PIXMAP_TYPE_WL, (uintptr_t)surface_resource)))
      {
         Eina_List *l;
+        E_Pixmap *ep = NULL;
 
-        ec = e_client_new(NULL, e_pixmap_new(E_PIXMAP_TYPE_WL, surface_resource), 1, 0);
+        ep = e_pixmap_find(E_PIXMAP_TYPE_WL, surface_resource);
+        if (!ep) ep = e_pixmap_new(E_PIXMAP_TYPE_WL, surface_resource);
+        EINA_SAFETY_ON_NULL_RETURN(ep);
+
+        ec = e_client_new(NULL, ep, 1, 0);
         if (!ec) return;
         ec->lock_focus_out = ec->layer_block = ec->visible = ec->override = 1;
         ec->new_client = 0;
index b28d6a0f77b6afa2f6a607f96ec258ba5a462170..185393429de3d988d9f56111ca9e00f0a4553e21 100644 (file)
@@ -9,6 +9,7 @@
 #endif
 
 static Eina_Hash *pixmaps[2] = {NULL};
+static Eina_Hash *deleted[2] = {NULL};
 static Eina_Hash *res_ids = NULL;
 static uint32_t res_id = 0;
 
@@ -247,10 +248,41 @@ e_pixmap_free(E_Pixmap *cp)
    _e_pixmap_hook_call(E_PIXMAP_HOOK_DEL, cp);
    e_pixmap_image_clear(cp, EINA_FALSE);
    if (cp->parent) eina_hash_set(pixmaps[cp->type], &cp->parent, NULL);
+   eina_hash_del_by_key(res_ids, &cp->res_id);
    eina_hash_del_by_key(pixmaps[cp->type], &cp->win);
+
+   if (e_pixmap_is_del(cp))
+     eina_hash_del_by_key(deleted[cp->type], &cp->win);
+   else
+     _e_pixmap_free(cp);
+
    return 0;
 }
 
+EAPI void
+e_pixmap_del(E_Pixmap *cp)
+{
+#if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
+   if (!cp) return;
+   if (cp->type != E_PIXMAP_TYPE_WL) return;
+   if (eina_hash_find(pixmaps[cp->type], &cp->win))
+     {
+        eina_hash_del_by_key(pixmaps[cp->type], &cp->win);
+        eina_hash_add(deleted[cp->type], &cp->win, cp);
+     }
+#endif
+}
+
+EAPI Eina_Bool
+e_pixmap_is_del(E_Pixmap *cp)
+{
+#if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
+   if (!cp) return 0;
+   if (cp->type != E_PIXMAP_TYPE_WL) return 0;
+   return !!eina_hash_find(deleted[cp->type], &cp->win);
+#endif
+}
+
 EAPI E_Pixmap *
 e_pixmap_ref(E_Pixmap *cp)
 {
@@ -307,12 +339,15 @@ e_pixmap_new(E_Pixmap_Type type, ...)
                }
           }
         else
-          pixmaps[type] = eina_hash_pointer_new((Eina_Free_Cb)_e_pixmap_free);
+          {
+             pixmaps[type] = eina_hash_pointer_new(NULL);
+             deleted[type] = eina_hash_pointer_new((Eina_Free_Cb)_e_pixmap_free);
+          }
         cp = _e_pixmap_new(type);
         cp->win = id;
         eina_hash_add(pixmaps[type], &id, cp);
         if (!res_ids)
-          res_ids = eina_hash_int32_new((Eina_Free_Cb)_e_pixmap_free);
+          res_ids = eina_hash_int32_new(NULL);
         cp->res_id = res_id;
         eina_hash_add(res_ids, &res_id, cp);
         res_id++;
index 4011f56d5b7c1d0705861fc2138ed4c4ef9662c4..0894d754f51067e6b9aa7349f7ee10e18fc73287 100644 (file)
@@ -33,6 +33,8 @@ struct _E_Pixmap_Hook
 };
 
 EAPI int e_pixmap_free(E_Pixmap *cp);
+EAPI void e_pixmap_del(E_Pixmap *cp);
+EAPI Eina_Bool e_pixmap_is_del(E_Pixmap *cp);
 EAPI E_Pixmap *e_pixmap_ref(E_Pixmap *cp);
 EAPI E_Pixmap *e_pixmap_new(E_Pixmap_Type type, ...);
 EAPI E_Pixmap_Type e_pixmap_type_get(const E_Pixmap *cp);
index 9445e24f08c27887df9e3db141989dcc5e8c9210..37bee456e26e2c94d81d5fd4fddaf0deccee8b96 100644 (file)
@@ -114,7 +114,17 @@ _e_elm_win_trap_show(void *data, Evas_Object *o)
              ecore_evas_title_set(ee, title);
 #if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
              if (type == E_PIXMAP_TYPE_WL)
-               cp = e_pixmap_new(type, wl_win_id);
+               {
+                  if ((cp = e_pixmap_find(type, wl_win_id)))
+                    {
+                       ERR("There is e_pixmap already, Delete old e_pixmap %p", cp);
+                       e_pixmap_del(cp);
+                       cp = NULL;
+                    }
+                  /* first creation of pixmap for internal window */
+                  if (!cp)
+                    cp = e_pixmap_new(type, wl_win_id);
+               }
              else
 #endif
                cp = e_pixmap_new(type, win);