evas canvas destruction - detect zombie objs and hack at them with axes
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>
Thu, 28 Jul 2016 15:00:49 +0000 (00:00 +0900)
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>
Thu, 28 Jul 2016 15:02:03 +0000 (00:02 +0900)
ok. so here's the issue at least now. we have eo objects in the canvas
and they have a refcount of 2 user_refcount is 0. the calls stack does
NOT show we are calling callbacks at that time on these objects. they
are not in the backtrace (the canvas is, the objects themselves are
not).

SOMETHING is keeping 2 eo "internal" refs on these objects and i have
no idea what/how/who. it's a royal pain in the butt to find out as the
only way is lots and lots of logging and you get drowned in the
logging...

so what I have now done is a super ugly workaround that detects these
zombie objects that refuse to die and just FORCES them to die when the
evas canvas frees and clears out layers.
ac10a00acc6bacf01bfd208cc78b4eb2a6a925d8 doesn't really cause the
issue, it just brings it out in the open for all to see far more
easily. but something is deeply wrong SOMEWHERE with SOME objects and
our refcounts.

this fixes T4187

src/lib/eo/Eo.h
src/lib/eo/eo.c
src/lib/evas/canvas/evas_main.c

index 293234a..f72ee69 100644 (file)
@@ -1132,6 +1132,12 @@ EAPI const Eo_Event_Description *eo_base_legacy_only_event_description_get(const
 /**
  * @}
  */
+
+
+   /* Private for EFL internal use only. Do not use these! */
+EAPI int ___eo_ref2_get(const Eo *obj_id);
+EAPI void ___eo_ref2_reset(const Eo *obj_id);
+
 #ifdef __cplusplus
 }
 #endif
index a7df2b5..0690c44 100644 (file)
@@ -1479,6 +1479,22 @@ eo_ref_get(const Eo *obj_id)
    return obj->user_refcount;
 }
 
+EAPI int
+___eo_ref2_get(const Eo *obj_id)
+{
+   EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, 0);
+
+   return obj->refcount;
+}
+
+EAPI void
+___eo_ref2_reset(const Eo *obj_id)
+{
+   EO_OBJ_POINTER_RETURN(obj_id, obj);
+   obj->refcount = 0;
+}
+
+
 EAPI void
 eo_del_intercept_set(Eo *obj_id, Eo_Del_Intercept del_intercept_func)
 {
index 7f7afa2..44959b3 100644 (file)
@@ -251,7 +251,9 @@ _evas_canvas_eo_base_destructor(Eo *eo_e, Evas_Public_Data *e)
         del = EINA_FALSE;
         EINA_INLIST_FOREACH(e->layers, lay)
           {
+             Eo *eo_obj;
              Evas_Object_Protected_Data *o;
+             Eina_List *unrefs = NULL;
 
              evas_layer_pre_free(lay);
 
@@ -264,9 +266,21 @@ _evas_canvas_eo_base_destructor(Eo *eo_e, Evas_Public_Data *e)
                             ERR("obj(%p, %s) ref count(%d) is bigger than 0. This object couldn't be deleted", o, o->type, eo_ref_get(o->object));
                             continue;
                          }
+                       else
+                         {
+                            unrefs = eina_list_append(unrefs, o->object);
+                         }
                        del = EINA_TRUE;
                     }
                }
+             EINA_LIST_FREE(unrefs, eo_obj)
+               {
+                  ERR("Killing Zombie Object [%p] ref=%i:%i\n", eo_obj, eo_ref_get(eo_obj), ___eo_ref2_get(eo_obj));
+                  ___eo_ref2_reset(eo_obj);
+                  while (eo_ref_get(eo_obj) > 1) eo_unref(eo_obj);
+                  while (eo_ref_get(eo_obj) < 1) eo_ref(eo_obj);
+                  eo_del(eo_obj);
+               }
           }
      }
    EINA_INLIST_FOREACH(e->layers, lay)