From 742fbc5717f3b70a4f3c900f648f9cc761985966 Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Fri, 29 Jul 2016 00:00:49 +0900 Subject: [PATCH] evas canvas destruction - detect zombie objs and hack at them with axes 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 | 6 ++++++ src/lib/eo/eo.c | 16 ++++++++++++++++ src/lib/evas/canvas/evas_main.c | 14 ++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h index 293234a..f72ee69 100644 --- a/src/lib/eo/Eo.h +++ b/src/lib/eo/Eo.h @@ -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 diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c index a7df2b5..0690c44 100644 --- a/src/lib/eo/eo.c +++ b/src/lib/eo/eo.c @@ -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) { diff --git a/src/lib/evas/canvas/evas_main.c b/src/lib/evas/canvas/evas_main.c index 7f7afa2..44959b3 100644 --- a/src/lib/evas/canvas/evas_main.c +++ b/src/lib/evas/canvas/evas_main.c @@ -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) -- 2.7.4