jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=2e96b5074dfb4212e72701db63de13222b9aa9b3

commit 2e96b5074dfb4212e72701db63de13222b9aa9b3
Author: Jean-Philippe Andre <[email protected]>
Date:   Wed Feb 15 14:43:35 2017 +0900

    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.
---
 src/lib/eo/eo.c         | 39 +++++++++++++++++++++++++++++++----
 src/lib/eo/eo_private.h | 55 +++++++++++++++++++++++++++----------------------
 2 files changed, 65 insertions(+), 29 deletions(-)

diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c
index 3722152..182a3a4 100644
--- a/src/lib/eo/eo.c
+++ b/src/lib/eo/eo.c
@@ -965,16 +965,47 @@ efl_reuse(const Eo *_obj)
 
 
 void
-_eo_free(_Eo_Object *obj)
+_eo_free(_Eo_Object *obj, Eina_Bool manual_free EINA_UNUSED)
 {
    _Efl_Class *klass = (_Efl_Class*) obj->klass;
 
    _eo_log_obj_free(obj);
 
 #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
    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;
    // rare to use goto to keep instruction cache cleaner
    if (!obj->destructed) goto err_not_destructed;
-   _eo_free(obj);
+   _eo_free(obj, EINA_TRUE);
    EO_OBJ_DONE(obj_id);
    return EINA_TRUE;
 
diff --git a/src/lib/eo/eo_private.h b/src/lib/eo/eo_private.h
index 7a6ed69..658c79f 100644
--- a/src/lib/eo/eo_private.h
+++ b/src/lib/eo/eo_private.h
@@ -274,7 +274,7 @@ _obj_is_override(_Eo_Object *obj)
    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 *
 _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;
 
         _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)
+
+        if (EINA_LIKELY(!obj->manual_free))
           {
-             Eina_Inlist *nitr = obj->data_xrefs->next;
-             Eo_Xref_Node *xref = EINA_INLIST_CONTAINER_GET(obj->data_xrefs, 
Eo_Xref_Node);
+#ifdef EO_DEBUG
+             /* If for some reason it's not empty, clear it. */
              Eo *obj_id = _eo_obj_id_get(obj);
-             if (obj_id == xref->ref_obj)
+             while (obj->xrefs)
                {
-                  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);
+                  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;
                }
-             else
+             while (obj->data_xrefs)
                {
-                  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_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;
                }
-
-             eina_freeq_ptr_main_add(xref, free, sizeof(*xref));
-             obj->data_xrefs = nitr;
-          }
 #endif
 
-        if (!obj->manual_free)
-          _eo_free(obj);
+             _eo_free(obj, EINA_FALSE);
+          }
         else
           _efl_ref(obj); /* If we manual free, we keep a phantom ref. */
      }

-- 


Reply via email to