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.
ac10a00acc 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
This commit is contained in:
Carsten Haitzler 2016-07-29 00:00:49 +09:00
parent 63a3da0c0f
commit 742fbc5717
3 changed files with 36 additions and 0 deletions

View 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

View 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)
{

View 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)