summaryrefslogtreecommitdiff
path: root/src/lib/eo
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2017-02-15 14:43:35 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2017-02-15 14:50:50 +0900
commit2e96b5074dfb4212e72701db63de13222b9aa9b3 (patch)
treebce9b7e179d3ac3ab4fedf24ca25e5053291f04a /src/lib/eo
parenta5535464bf1eb436b612895a5ee647a670641989 (diff)
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.
Diffstat (limited to 'src/lib/eo')
-rw-r--r--src/lib/eo/eo.c39
-rw-r--r--src/lib/eo/eo_private.h55
2 files changed, 65 insertions, 29 deletions
diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c
index 3722152b9e..182a3a464d 100644
--- a/src/lib/eo/eo.c
+++ b/src/lib/eo/eo.c
@@ -965,16 +965,47 @@ efl_reuse(const Eo *_obj)
965 965
966 966
967void 967void
968_eo_free(_Eo_Object *obj) 968_eo_free(_Eo_Object *obj, Eina_Bool manual_free EINA_UNUSED)
969{ 969{
970 _Efl_Class *klass = (_Efl_Class*) obj->klass; 970 _Efl_Class *klass = (_Efl_Class*) obj->klass;
971 971
972 _eo_log_obj_free(obj); 972 _eo_log_obj_free(obj);
973 973
974#ifdef EO_DEBUG 974#ifdef EO_DEBUG
975 if (obj->datarefcount) 975 if (manual_free)
976 { 976 {
977 ERR("Object %p data still referenced %d time(s).", obj, obj->datarefcount); 977 Eo *obj_id = _eo_obj_id_get(obj);
978 if (obj->datarefcount)
979 {
980 ERR("Object %p data still referenced %d time(s).", obj_id, obj->datarefcount);
981 }
982 while (obj->xrefs)
983 {
984 Eina_Inlist *nitr = obj->xrefs->next;
985 Eo_Xref_Node *xref = EINA_INLIST_CONTAINER_GET(obj->data_xrefs, Eo_Xref_Node);
986 ERR("Object %p is still referenced by object %p. Origin: %s:%d",
987 obj_id, xref->ref_obj, xref->file, xref->line);
988 eina_freeq_ptr_main_add(xref, free, sizeof(*xref));
989 obj->xrefs = nitr;
990 }
991 while (obj->data_xrefs)
992 {
993 Eina_Inlist *nitr = obj->data_xrefs->next;
994 Eo_Xref_Node *xref = EINA_INLIST_CONTAINER_GET(obj->data_xrefs, Eo_Xref_Node);
995 if (obj_id == xref->ref_obj)
996 {
997 WRN("Object %p still has a reference to its own data (subclass: %s). Origin: %s:%d",
998 obj_id, xref->data_klass, xref->file, xref->line);
999 }
1000 else
1001 {
1002 ERR("Data of object %p (subclass: %s) is still referenced by object %p. Origin: %s:%d",
1003 obj_id, xref->data_klass, xref->ref_obj, xref->file, xref->line);
1004 }
1005
1006 eina_freeq_ptr_main_add(xref, free, sizeof(*xref));
1007 obj->data_xrefs = nitr;
1008 }
978 } 1009 }
979#endif 1010#endif
980 if (_obj_is_override(obj)) 1011 if (_obj_is_override(obj))
@@ -2362,7 +2393,7 @@ efl_manual_free(Eo *obj_id)
2362 if (obj->manual_free == EINA_FALSE) goto err_manual_free; 2393 if (obj->manual_free == EINA_FALSE) goto err_manual_free;
2363 // rare to use goto to keep instruction cache cleaner 2394 // rare to use goto to keep instruction cache cleaner
2364 if (!obj->destructed) goto err_not_destructed; 2395 if (!obj->destructed) goto err_not_destructed;
2365 _eo_free(obj); 2396 _eo_free(obj, EINA_TRUE);
2366 EO_OBJ_DONE(obj_id); 2397 EO_OBJ_DONE(obj_id);
2367 return EINA_TRUE; 2398 return EINA_TRUE;
2368 2399
diff --git a/src/lib/eo/eo_private.h b/src/lib/eo/eo_private.h
index 7a6ed69b93..658c79f7fe 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)
274 return (obj->vtable != &obj->klass->vtable); 274 return (obj->vtable != &obj->klass->vtable);
275} 275}
276 276
277void _eo_free(_Eo_Object *obj); 277void _eo_free(_Eo_Object *obj, Eina_Bool manual_free);
278 278
279static inline _Eo_Object * 279static inline _Eo_Object *
280_efl_ref(_Eo_Object *obj) 280_efl_ref(_Eo_Object *obj)
@@ -322,38 +322,43 @@ _efl_unref_internal(_Eo_Object *obj, const char *func_name, const char *file, in
322 obj->del_triggered = EINA_TRUE; 322 obj->del_triggered = EINA_TRUE;
323 323
324 _efl_del_internal(obj, func_name, file, line); 324 _efl_del_internal(obj, func_name, file, line);
325#ifdef EO_DEBUG 325
326 /* If for some reason it's not empty, clear it. */ 326 if (EINA_LIKELY(!obj->manual_free))
327 while (obj->xrefs)
328 {
329 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);
330 Eina_Inlist *nitr = obj->xrefs->next;
331 eina_freeq_ptr_main_add(EINA_INLIST_CONTAINER_GET(obj->xrefs, Eo_Xref_Node), free, 0);
332 obj->xrefs = nitr;
333 }
334 while (obj->data_xrefs)
335 { 327 {
336 Eina_Inlist *nitr = obj->data_xrefs->next; 328#ifdef EO_DEBUG
337 Eo_Xref_Node *xref = EINA_INLIST_CONTAINER_GET(obj->data_xrefs, Eo_Xref_Node); 329 /* If for some reason it's not empty, clear it. */
338 Eo *obj_id = _eo_obj_id_get(obj); 330 Eo *obj_id = _eo_obj_id_get(obj);
339 if (obj_id == xref->ref_obj) 331 while (obj->xrefs)
340 { 332 {
341 WRN("in %s:%d: func '%s' Object %p still has a reference to its own data (subclass: %s). Origin: %s:%d", 333 Eina_Inlist *nitr = obj->xrefs->next;
342 file, line, func_name, obj_id, xref->data_klass, xref->file, xref->line); 334 Eo_Xref_Node *xref = EINA_INLIST_CONTAINER_GET(obj->data_xrefs, Eo_Xref_Node);
335 ERR("in %s:%d: func '%s' Object %p is still referenced by object %p. Origin: %s:%d",
336 file, line, func_name, obj_id, xref->ref_obj, xref->file, xref->line);
337 eina_freeq_ptr_main_add(xref, free, sizeof(*xref));
338 obj->xrefs = nitr;
343 } 339 }
344 else 340 while (obj->data_xrefs)
345 { 341 {
346 ERR("in %s:%d: func '%s' Data of object %p (subclass: %s) is still referenced by object %p. Origin: %s:%d", 342 Eina_Inlist *nitr = obj->data_xrefs->next;
347 file, line, func_name, obj_id, xref->data_klass, xref->ref_obj, xref->file, xref->line); 343 Eo_Xref_Node *xref = EINA_INLIST_CONTAINER_GET(obj->data_xrefs, Eo_Xref_Node);
344 if (obj_id == xref->ref_obj)
345 {
346 WRN("in %s:%d: func '%s' Object %p still has a reference to its own data (subclass: %s). Origin: %s:%d",
347 file, line, func_name, obj_id, xref->data_klass, xref->file, xref->line);
348 }
349 else
350 {
351 ERR("in %s:%d: func '%s' Data of object %p (subclass: %s) is still referenced by object %p. Origin: %s:%d",
352 file, line, func_name, obj_id, xref->data_klass, xref->ref_obj, xref->file, xref->line);
353 }
354
355 eina_freeq_ptr_main_add(xref, free, sizeof(*xref));
356 obj->data_xrefs = nitr;
348 } 357 }
349
350 eina_freeq_ptr_main_add(xref, free, sizeof(*xref));
351 obj->data_xrefs = nitr;
352 }
353#endif 358#endif
354 359
355 if (!obj->manual_free) 360 _eo_free(obj, EINA_FALSE);
356 _eo_free(obj); 361 }
357 else 362 else
358 _efl_ref(obj); /* If we manual free, we keep a phantom ref. */ 363 _efl_ref(obj); /* If we manual free, we keep a phantom ref. */
359 } 364 }