forked from enlightenment/efl
eo_debug: Improve dangling xref debug logs even more
In case of manual free, as is heavily used by Evas, we can't really print an ERR if there are still references before free has been called. This may not be ideal from a pure EO point of view but considering how Evas uses manual free this is the best solution to avoid polluting debug logs.
This commit is contained in:
parent
a5535464bf
commit
2e96b5074d
|
@ -965,16 +965,47 @@ efl_reuse(const Eo *_obj)
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_eo_free(_Eo_Object *obj)
|
_eo_free(_Eo_Object *obj, Eina_Bool manual_free EINA_UNUSED)
|
||||||
{
|
{
|
||||||
_Efl_Class *klass = (_Efl_Class*) obj->klass;
|
_Efl_Class *klass = (_Efl_Class*) obj->klass;
|
||||||
|
|
||||||
_eo_log_obj_free(obj);
|
_eo_log_obj_free(obj);
|
||||||
|
|
||||||
#ifdef EO_DEBUG
|
#ifdef EO_DEBUG
|
||||||
if (obj->datarefcount)
|
if (manual_free)
|
||||||
{
|
{
|
||||||
ERR("Object %p data still referenced %d time(s).", obj, obj->datarefcount);
|
Eo *obj_id = _eo_obj_id_get(obj);
|
||||||
|
if (obj->datarefcount)
|
||||||
|
{
|
||||||
|
ERR("Object %p data still referenced %d time(s).", obj_id, obj->datarefcount);
|
||||||
|
}
|
||||||
|
while (obj->xrefs)
|
||||||
|
{
|
||||||
|
Eina_Inlist *nitr = obj->xrefs->next;
|
||||||
|
Eo_Xref_Node *xref = EINA_INLIST_CONTAINER_GET(obj->data_xrefs, Eo_Xref_Node);
|
||||||
|
ERR("Object %p is still referenced by object %p. Origin: %s:%d",
|
||||||
|
obj_id, xref->ref_obj, xref->file, xref->line);
|
||||||
|
eina_freeq_ptr_main_add(xref, free, sizeof(*xref));
|
||||||
|
obj->xrefs = nitr;
|
||||||
|
}
|
||||||
|
while (obj->data_xrefs)
|
||||||
|
{
|
||||||
|
Eina_Inlist *nitr = obj->data_xrefs->next;
|
||||||
|
Eo_Xref_Node *xref = EINA_INLIST_CONTAINER_GET(obj->data_xrefs, Eo_Xref_Node);
|
||||||
|
if (obj_id == xref->ref_obj)
|
||||||
|
{
|
||||||
|
WRN("Object %p still has a reference to its own data (subclass: %s). Origin: %s:%d",
|
||||||
|
obj_id, xref->data_klass, xref->file, xref->line);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERR("Data of object %p (subclass: %s) is still referenced by object %p. Origin: %s:%d",
|
||||||
|
obj_id, xref->data_klass, xref->ref_obj, xref->file, xref->line);
|
||||||
|
}
|
||||||
|
|
||||||
|
eina_freeq_ptr_main_add(xref, free, sizeof(*xref));
|
||||||
|
obj->data_xrefs = nitr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (_obj_is_override(obj))
|
if (_obj_is_override(obj))
|
||||||
|
@ -2362,7 +2393,7 @@ efl_manual_free(Eo *obj_id)
|
||||||
if (obj->manual_free == EINA_FALSE) goto err_manual_free;
|
if (obj->manual_free == EINA_FALSE) goto err_manual_free;
|
||||||
// rare to use goto to keep instruction cache cleaner
|
// rare to use goto to keep instruction cache cleaner
|
||||||
if (!obj->destructed) goto err_not_destructed;
|
if (!obj->destructed) goto err_not_destructed;
|
||||||
_eo_free(obj);
|
_eo_free(obj, EINA_TRUE);
|
||||||
EO_OBJ_DONE(obj_id);
|
EO_OBJ_DONE(obj_id);
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
|
|
||||||
|
|
|
@ -274,7 +274,7 @@ _obj_is_override(_Eo_Object *obj)
|
||||||
return (obj->vtable != &obj->klass->vtable);
|
return (obj->vtable != &obj->klass->vtable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _eo_free(_Eo_Object *obj);
|
void _eo_free(_Eo_Object *obj, Eina_Bool manual_free);
|
||||||
|
|
||||||
static inline _Eo_Object *
|
static inline _Eo_Object *
|
||||||
_efl_ref(_Eo_Object *obj)
|
_efl_ref(_Eo_Object *obj)
|
||||||
|
@ -322,38 +322,43 @@ _efl_unref_internal(_Eo_Object *obj, const char *func_name, const char *file, in
|
||||||
obj->del_triggered = EINA_TRUE;
|
obj->del_triggered = EINA_TRUE;
|
||||||
|
|
||||||
_efl_del_internal(obj, func_name, file, line);
|
_efl_del_internal(obj, func_name, file, line);
|
||||||
#ifdef EO_DEBUG
|
|
||||||
/* If for some reason it's not empty, clear it. */
|
|
||||||
while (obj->xrefs)
|
|
||||||
{
|
|
||||||
ERR("in %s:%d: func '%s' obj->xrefs is not empty, possibly a bug, please report. - An error will be reported for each xref in the stack.", file, line, func_name);
|
|
||||||
Eina_Inlist *nitr = obj->xrefs->next;
|
|
||||||
eina_freeq_ptr_main_add(EINA_INLIST_CONTAINER_GET(obj->xrefs, Eo_Xref_Node), free, 0);
|
|
||||||
obj->xrefs = nitr;
|
|
||||||
}
|
|
||||||
while (obj->data_xrefs)
|
|
||||||
{
|
|
||||||
Eina_Inlist *nitr = obj->data_xrefs->next;
|
|
||||||
Eo_Xref_Node *xref = EINA_INLIST_CONTAINER_GET(obj->data_xrefs, Eo_Xref_Node);
|
|
||||||
Eo *obj_id = _eo_obj_id_get(obj);
|
|
||||||
if (obj_id == xref->ref_obj)
|
|
||||||
{
|
|
||||||
WRN("in %s:%d: func '%s' Object %p still has a reference to its own data (subclass: %s). Origin: %s:%d",
|
|
||||||
file, line, func_name, obj_id, xref->data_klass, xref->file, xref->line);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ERR("in %s:%d: func '%s' Data of object %p (subclass: %s) is still referenced by object %p. Origin: %s:%d",
|
|
||||||
file, line, func_name, obj_id, xref->data_klass, xref->ref_obj, xref->file, xref->line);
|
|
||||||
}
|
|
||||||
|
|
||||||
eina_freeq_ptr_main_add(xref, free, sizeof(*xref));
|
if (EINA_LIKELY(!obj->manual_free))
|
||||||
obj->data_xrefs = nitr;
|
{
|
||||||
}
|
#ifdef EO_DEBUG
|
||||||
|
/* If for some reason it's not empty, clear it. */
|
||||||
|
Eo *obj_id = _eo_obj_id_get(obj);
|
||||||
|
while (obj->xrefs)
|
||||||
|
{
|
||||||
|
Eina_Inlist *nitr = obj->xrefs->next;
|
||||||
|
Eo_Xref_Node *xref = EINA_INLIST_CONTAINER_GET(obj->data_xrefs, Eo_Xref_Node);
|
||||||
|
ERR("in %s:%d: func '%s' Object %p is still referenced by object %p. Origin: %s:%d",
|
||||||
|
file, line, func_name, obj_id, xref->ref_obj, xref->file, xref->line);
|
||||||
|
eina_freeq_ptr_main_add(xref, free, sizeof(*xref));
|
||||||
|
obj->xrefs = nitr;
|
||||||
|
}
|
||||||
|
while (obj->data_xrefs)
|
||||||
|
{
|
||||||
|
Eina_Inlist *nitr = obj->data_xrefs->next;
|
||||||
|
Eo_Xref_Node *xref = EINA_INLIST_CONTAINER_GET(obj->data_xrefs, Eo_Xref_Node);
|
||||||
|
if (obj_id == xref->ref_obj)
|
||||||
|
{
|
||||||
|
WRN("in %s:%d: func '%s' Object %p still has a reference to its own data (subclass: %s). Origin: %s:%d",
|
||||||
|
file, line, func_name, obj_id, xref->data_klass, xref->file, xref->line);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERR("in %s:%d: func '%s' Data of object %p (subclass: %s) is still referenced by object %p. Origin: %s:%d",
|
||||||
|
file, line, func_name, obj_id, xref->data_klass, xref->ref_obj, xref->file, xref->line);
|
||||||
|
}
|
||||||
|
|
||||||
|
eina_freeq_ptr_main_add(xref, free, sizeof(*xref));
|
||||||
|
obj->data_xrefs = nitr;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!obj->manual_free)
|
_eo_free(obj, EINA_FALSE);
|
||||||
_eo_free(obj);
|
}
|
||||||
else
|
else
|
||||||
_efl_ref(obj); /* If we manual free, we keep a phantom ref. */
|
_efl_ref(obj); /* If we manual free, we keep a phantom ref. */
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue