eo: improve logs by always showing event source, minor refactor.

Instead of 2 sets of macro, one for HAVE_EO_ID and another without,
use a single set of macros and have the implementation of
_eo_class_pointer_get() and _eo_obj_pointer_get() to do the actual

These functions now take the source information so the logs reflect
that and not always the same function.
This commit is contained in:
Gustavo Sverzut Barbieri 2016-12-02 16:26:46 -02:00
parent 515d894fe9
commit dfe3a4ad40
5 changed files with 148 additions and 123 deletions

View File

@ -249,11 +249,28 @@ _eo_is_a_class(const Eo *eo_id)
}
static inline _Efl_Class *
_eo_class_pointer_get(const Efl_Class *klass_id)
_eo_class_pointer_get(const Efl_Class *klass_id, const char *func_name, const char *file, int line)
{
#ifdef HAVE_EO_ID
return ID_CLASS_GET((Eo_Id)klass_id);
(void)func_name;
(void)file;
(void)line;
#else
Eo_Header *klass = (Eo_Header *)klass_id;
if (EINA_UNLIKELY(!klass))
{
eina_log_print(_eo_log_dom,
EINA_LOG_LEVEL_DBG,
file, func_name, line,
"klass_id is NULL. Possibly unintended access?");
return NULL;
}
if (EINA_UNLIKELY(!EINA_MAGIC_CHECK(klass, EO_CLASS_EINA_MAGIC)))
{
eina_magic_fail(klass, klass->__magic, EO_CLASS_EINA_MAGIC, file, func_name, line);
return NULL;
}
return (_Efl_Class *) klass_id;
#endif
}
@ -369,7 +386,7 @@ _efl_object_call_resolve(Eo *eo_id, const char *func_name, Efl_Object_Op_Call_Da
if (is_obj)
{
EO_OBJ_POINTER_RETURN_VAL(eo_id, _obj, EINA_FALSE);
EO_OBJ_POINTER_RETURN_VAL_PROXY(eo_id, _obj, EINA_FALSE);
obj = _obj;
klass = _obj->klass;
@ -479,7 +496,7 @@ end:
Eo *emb_obj_id;
EINA_LIST_FOREACH(obj->composite_objects, itr, emb_obj_id)
{
EO_OBJ_POINTER(emb_obj_id, emb_obj);
EO_OBJ_POINTER_PROXY(emb_obj_id, emb_obj);
if (EINA_UNLIKELY(!emb_obj)) continue;
func = _vtable_func_get(emb_obj->vtable, cache->op);
@ -543,7 +560,7 @@ ok_cur_klass:
ok_klass:
{
EO_CLASS_POINTER_GOTO(eo_id, _klass, err_klass);
EO_CLASS_POINTER_GOTO_PROXY(eo_id, _klass, err_klass);
klass = _klass;
vtable = &klass->vtable;
call->obj = NULL;
@ -728,16 +745,17 @@ err_klass:
EAPI Eo *
_efl_add_internal_start(const char *file, int line, const Efl_Class *klass_id, Eo *parent_id, Eina_Bool ref EINA_UNUSED, Eina_Bool is_fallback)
{
const char *func_name = __FUNCTION__;
_Eo_Object *obj;
Eo_Stack_Frame *fptr = NULL;
if (is_fallback) fptr = _efl_add_fallback_stack_push(NULL);
EO_CLASS_POINTER_GOTO(klass_id, klass, err_klass);
EO_CLASS_POINTER_GOTO_PROXY(klass_id, klass, err_klass);
if (parent_id)
{
EO_OBJ_POINTER_GOTO(parent_id, parent, err_parent);
EO_OBJ_POINTER_GOTO_PROXY(parent_id, parent, err_parent);
}
// not likely so use goto to alleviate l1 instruction cache of rare code
@ -787,7 +805,7 @@ ok_nomatch_back:
ok_nomatch:
{
EO_OBJ_POINTER_GOTO(eo_id, new_obj, err_newid);
EO_OBJ_POINTER_GOTO_PROXY(eo_id, new_obj, err_newid);
/* We have two refs at this point. */
_efl_unref(obj);
efl_del((Eo *)obj->header.id);
@ -1171,18 +1189,17 @@ efl_class_new(const Efl_Class_Description *desc, const Efl_Class *parent_id, ...
va_list p_list;
size_t extn_sz, mro_sz, mixins_sz;
Eina_List *extn_list, *mro, *mixins;
_Efl_Class *parent = NULL;
EINA_SAFETY_ON_NULL_RETURN_VAL(desc, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(desc->name, NULL);
_Efl_Class *parent = _eo_class_pointer_get(parent_id);
#ifndef HAVE_EO_ID
if (parent && !EINA_MAGIC_CHECK((Eo_Header *) parent, EO_CLASS_EINA_MAGIC))
if (parent_id)
{
EINA_MAGIC_FAIL((Eo_Header *) parent, EO_CLASS_EINA_MAGIC);
return NULL;
parent = _eo_class_pointer_get(parent_id, __FUNCTION__, __FILE__, __LINE__);
if (!parent)
return NULL;
}
#endif
/* Check restrictions on Interface types. */
if (desc->type == EFL_CLASS_TYPE_INTERFACE)
@ -1231,7 +1248,7 @@ efl_class_new(const Efl_Class_Description *desc, const Efl_Class *parent_id, ...
extn_id = va_arg(p_list, Eo_Id *);
while (extn_id)
{
extn = _eo_class_pointer_get((Efl_Class *)extn_id);
extn = _eo_class_pointer_get((Efl_Class *)extn_id, __FUNCTION__, __FILE__, __LINE__);
switch (extn->desc->type)
{
case EFL_CLASS_TYPE_REGULAR_NO_INSTANT:
@ -1564,7 +1581,8 @@ efl_xref_internal(const char *file, int line, Eo *obj_id, const Eo *ref_obj_id)
efl_ref(obj_id);
#ifdef EO_DEBUG
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, obj_id);
const char *func_name = __FUNCTION__;
EO_OBJ_POINTER_RETURN_VAL_PROXY(obj_id, obj, obj_id);
Eo_Xref_Node *xref = calloc(1, sizeof(*xref));
xref->ref_obj = ref_obj_id;
@ -1848,13 +1866,14 @@ efl_data_xref_internal(const char *file, int line, const Eo *obj_id, const Efl_C
{
void *ret = NULL;
_Efl_Class *klass = NULL;
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, NULL);
EO_OBJ_POINTER(ref_obj_id, ref_obj);
const char *func_name = __FUNCTION__;
EO_OBJ_POINTER_RETURN_VAL_PROXY(obj_id, obj, NULL);
EO_OBJ_POINTER_PROXY(ref_obj_id, ref_obj);
if (ref_obj)
{
if (klass_id)
{
EO_CLASS_POINTER_GOTO(klass_id, klass2, err_klass);
EO_CLASS_POINTER_GOTO_PROXY(klass_id, klass2, err_klass);
klass = klass2;
#ifdef EO_DEBUG
// rare to use goto to keep instruction cache cleaner

View File

@ -209,7 +209,7 @@ Eo *_eo_header_id_get(const Eo_Header *header)
}
/* Retrieves the pointer to the object from the id */
_Eo_Object *_eo_obj_pointer_get(const Eo_Id obj_id);
_Eo_Object *_eo_obj_pointer_get(const Eo_Id obj_id, const char *func_name, const char *file, int line);
void _eo_obj_pointer_done(const Eo_Id obj_id);
static inline
@ -231,7 +231,7 @@ _eo_condtor_reset(_Eo_Object *obj)
}
static inline void
_efl_del_internal(const char *file, int line, _Eo_Object *obj)
_efl_del_internal(_Eo_Object *obj, const char *func_name, const char *file, int line)
{
/* We need that for the event callbacks that may ref/unref. */
obj->refcount++;
@ -246,8 +246,8 @@ _efl_del_internal(const char *file, int line, _Eo_Object *obj)
if (!obj->condtor_done)
{
ERR("in %s:%d: Object of class '%s' - Not all of the object destructors have been executed.",
file, line, klass->desc->name);
ERR("in %s:%d: func '%s' Object of class '%s' - Not all of the object destructors have been executed.",
file, line, func_name, klass->desc->name);
}
/*FIXME: add eo_class_unref(klass) ? - just to clear the caches. */
@ -310,27 +310,28 @@ _efl_ref(_Eo_Object *obj)
return obj;
}
#define _efl_unref(obj) _efl_unref_internal(obj, __FUNCTION__, __FILE__, __LINE__)
static inline void
_efl_unref(_Eo_Object *obj)
_efl_unref_internal(_Eo_Object *obj, const char *func_name, const char *file, int line)
{
--(obj->refcount);
if (EINA_UNLIKELY(obj->refcount <= 0))
{
if (obj->refcount < 0)
{
ERR("Obj:%p. Refcount (%d) < 0. Too many unrefs.", obj, obj->refcount);
ERR("in %s:%d: func '%s' Obj:%p. Refcount (%d) < 0. Too many unrefs.", file, line, func_name, obj, obj->refcount);
return;
}
if (obj->destructed)
{
ERR("Object %p already destructed.", _eo_obj_id_get(obj));
ERR("in %s:%d: func '%s' Object %p already destructed.", file, line, func_name, _eo_obj_id_get(obj));
return;
}
if (obj->del_triggered)
{
ERR("Object %p deletion already triggered. You wrongly call efl_unref() within a destructor.", _eo_obj_id_get(obj));
ERR("in %s:%d: func '%s' Object %p deletion already triggered. You wrongly call efl_unref() within a destructor.", file, line, func_name, _eo_obj_id_get(obj));
return;
}
@ -344,12 +345,12 @@ _efl_unref(_Eo_Object *obj)
obj->del_triggered = EINA_TRUE;
_efl_del_internal(__FILE__, __LINE__, obj);
_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("obj->xrefs is not empty, possibly a bug, please report. - An error will be reported for each xref in the stack.");
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;
@ -358,7 +359,7 @@ _efl_unref(_Eo_Object *obj)
{
Eina_Inlist *nitr = obj->data_xrefs->next;
Eo_Xref_Node *xref = EINA_INLIST_CONTAINER_GET(obj->data_xrefs, Eo_Xref_Node);
ERR("Data of object 0x%lx is still referenced by object %p", (unsigned long) _eo_obj_id_get(obj), xref->ref_obj);
ERR("in %s:%d: func '%s' Data of object 0x%lx is still referenced by object %p", file, line, func_name, (unsigned long) _eo_obj_id_get(obj), xref->ref_obj);
eina_freeq_ptr_main_add(xref, free, sizeof(*xref));
obj->data_xrefs = nitr;

View File

@ -28,7 +28,10 @@ _eo_pointer_error(const char *func_name, const char *file, int line, const char
static void
_eo_obj_pointer_invalid(const Eo_Id obj_id,
Eo_Id_Data *data,
unsigned char domain)
unsigned char domain,
const char *func_name,
const char *file,
int line)
{
Eina_Thread thread = eina_thread_self();
const char *tself = "main";
@ -40,13 +43,14 @@ _eo_obj_pointer_invalid(const Eo_Id obj_id,
snprintf(tbuf, sizeof(tbuf), "%p", (void *)thread);
tself = tbuf;
}
ERR("EOID %p is not a valid %s. "
eina_log_print(_eo_log_dom, EINA_LOG_LEVEL_ERR,
file, func_name, line,
"EOID %p is not a valid %s. "
"EOID domain=%i, current_domain=%i, local_domain=%i. "
"EOID generation=%lx, id=%lx, ref=%i, super=%i. "
"Thread self=%s. "
"Available domains [%s %s %s %s]. "
"Maybe it has been deleted or does not belong to your thread?",
(void *)obj_id,
type,
(int)domain,
@ -66,7 +70,7 @@ _eo_obj_pointer_invalid(const Eo_Id obj_id,
#endif
_Eo_Object *
_eo_obj_pointer_get(const Eo_Id obj_id)
_eo_obj_pointer_get(const Eo_Id obj_id, const char *func_name, const char *file, int line)
{
#ifdef HAVE_EO_ID
_Eo_Id_Entry *entry;
@ -168,14 +172,31 @@ _eo_obj_pointer_get(const Eo_Id obj_id)
err_shared_null:
eina_lock_release(&(_eo_table_data_shared_data->obj_lock));
err_null:
DBG("obj_id is NULL. Possibly unintended access?");
eina_log_print(_eo_log_dom,
EINA_LOG_LEVEL_DBG,
file, func_name, line,
"obj_id is NULL. Possibly unintended access?");
return NULL;
err_shared:
eina_lock_release(&(_eo_table_data_shared_data->obj_lock));
err:
_eo_obj_pointer_invalid(obj_id, data, domain);
_eo_obj_pointer_invalid(obj_id, data, domain, func_name, file, line);
return NULL;
#else
Eo_Header *obj = (Eo_Header *)obj_id;
if (EINA_UNLIKELY(!obj))
{
eina_log_print(_eo_log_dom,
EINA_LOG_LEVEL_DBG,
file, func_name, line,
"obj_id is NULL. Possibly unintended access?");
return NULL;
}
if (EINA_UNLIKELY(!EINA_MAGIC_CHECK(obj, EO_EINA_MAGIC)))
{
eina_magic_fail(obj, obj->__magic, EO_EINA_MAGIC, file, func_name, line);
return NULL;
}
return (_Eo_Object *) obj_id;
#endif
}
@ -188,4 +209,5 @@ _eo_obj_pointer_done(const Eo_Id obj_id)
if (EINA_LIKELY(domain != EFL_ID_DOMAIN_SHARED)) return;
eina_lock_release(&(_eo_table_data_shared_data->obj_lock));
#endif
(void)obj_id;
}

View File

@ -6,8 +6,6 @@
/* Macro used to obtain the object pointer and return if fails. */
#ifdef HAVE_EO_ID
void _eo_pointer_error(const char *func_name, const char *file, int line, const char *fmt, ...);
#define _EO_POINTER_ERR(fmt, ...) \
@ -16,40 +14,84 @@ void _eo_pointer_error(const char *func_name, const char *file, int line, const
#define EO_OBJ_POINTER(obj_id, obj) \
_Eo_Object *obj; \
do { \
obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
obj = _eo_obj_pointer_get((Eo_Id)obj_id, __FUNCTION__, __FILE__, __LINE__); \
} while (0)
#define EO_OBJ_POINTER_PROXY(obj_id, obj) \
_Eo_Object *obj; \
do { \
obj = _eo_obj_pointer_get((Eo_Id)obj_id, func_name, file, line); \
} while (0)
#define EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, ret) \
_Eo_Object *obj; \
do { \
obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
obj = _eo_obj_pointer_get((Eo_Id)obj_id, __FUNCTION__, __FILE__, __LINE__); \
if (!obj) return (ret); \
} while (0)
/* reports as another function using func_name, file and line variables */
#define EO_OBJ_POINTER_RETURN_VAL_PROXY(obj_id, obj, ret) \
_Eo_Object *obj; \
do { \
obj = _eo_obj_pointer_get((Eo_Id)obj_id, func_name, file, line); \
if (!obj) return (ret); \
} while (0)
#define EO_OBJ_POINTER_RETURN(obj_id, obj) \
_Eo_Object *obj; \
do { \
obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
obj = _eo_obj_pointer_get((Eo_Id)obj_id, __FUNCTION__, __FILE__, __LINE__); \
if (!obj) return; \
} while (0)
#define EO_OBJ_POINTER_RETURN_PROXY(obj_id, obj) \
_Eo_Object *obj; \
do { \
obj = _eo_obj_pointer_get((Eo_Id)obj_id, func_name, file, line); \
if (!obj) return; \
} while (0)
#define EO_OBJ_POINTER_GOTO(obj_id, obj, label) \
_Eo_Object *obj; \
do { \
obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
obj = _eo_obj_pointer_get((Eo_Id)obj_id, __FUNCTION__, __FILE__, __LINE__); \
if (!obj) goto label; \
} while (0)
#define EO_OBJ_POINTER_GOTO_PROXY(obj_id, obj, label) \
_Eo_Object *obj; \
do { \
obj = _eo_obj_pointer_get((Eo_Id)obj_id, func_name, file, line); \
if (!obj) goto label; \
} while (0)
#define EO_CLASS_POINTER(klass_id, klass) \
_Efl_Class *klass; \
do { \
klass = _eo_class_pointer_get(klass_id); \
klass = _eo_class_pointer_get(klass_id, __FUNCTION__, __FILE__, __LINE__); \
} while (0)
#define EO_CLASS_POINTER_PROXY(klass_id, klass) \
_Efl_Class *klass; \
do { \
klass = _eo_class_pointer_get(klass_id, func_name, file, line); \
} while (0)
#define EO_CLASS_POINTER_RETURN_VAL(klass_id, klass, ret) \
_Efl_Class *klass; \
do { \
klass = _eo_class_pointer_get(klass_id); \
klass = _eo_class_pointer_get(klass_id, __FUNCTION__, __FILE__, __LINE__); \
if (!klass) { \
_EO_POINTER_ERR("Class (%p) is an invalid ref.", klass_id); \
return ret; \
} \
} while (0)
#define EO_CLASS_POINTER_RETURN_VAL_PROXY(klass_id, klass, ret) \
_Efl_Class *klass; \
do { \
klass = _eo_class_pointer_get(klass_id, func_name, file, line); \
if (!klass) { \
_EO_POINTER_ERR("Class (%p) is an invalid ref.", klass_id); \
return ret; \
@ -59,7 +101,17 @@ void _eo_pointer_error(const char *func_name, const char *file, int line, const
#define EO_CLASS_POINTER_RETURN(klass_id, klass) \
_Efl_Class *klass; \
do { \
klass = _eo_class_pointer_get(klass_id); \
klass = _eo_class_pointer_get(klass_id, __FUNCTION__, __FILE__, __LINE__); \
if (!klass) { \
_EO_POINTER_ERR("Class (%p) is an invalid ref.", klass_id); \
return; \
} \
} while (0)
#define EO_CLASS_POINTER_RETURN_PROXY(klass_id, klass) \
_Efl_Class *klass; \
do { \
klass = _eo_class_pointer_get(klass_id, func_name, file, line); \
if (!klass) { \
_EO_POINTER_ERR("Class (%p) is an invalid ref.", klass_id); \
return; \
@ -69,92 +121,22 @@ void _eo_pointer_error(const char *func_name, const char *file, int line, const
#define EO_CLASS_POINTER_GOTO(klass_id, klass, label) \
_Efl_Class *klass; \
do { \
klass = _eo_class_pointer_get(klass_id); \
klass = _eo_class_pointer_get(klass_id, __FUNCTION__, __FILE__, __LINE__); \
if (!klass) goto label; \
} while (0)
#define EO_CLASS_POINTER_GOTO_PROXY(klass_id, klass, label) \
_Efl_Class *klass; \
do { \
klass = _eo_class_pointer_get(klass_id, func_name, file, line); \
if (!klass) goto label; \
} while (0)
#define EO_OBJ_DONE(obj_id) \
_eo_obj_pointer_done((Eo_Id)obj_id)
#else
#define EO_OBJ_POINTER(obj_id, obj) \
_Eo_Object *obj; \
do { \
obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
if (obj && \
!EINA_MAGIC_CHECK((Eo_Header *) obj, EO_EINA_MAGIC)) { \
EINA_MAGIC_FAIL((Eo_Header *) obj, EO_EINA_MAGIC); \
} \
} while (0)
#define EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, ret) \
_Eo_Object *obj; \
do { \
obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
if (!obj) return (ret); \
EO_MAGIC_RETURN_VAL((Eo_Header *) obj, EO_EINA_MAGIC, ret); \
} while (0)
#define EO_OBJ_POINTER_RETURN(obj_id, obj) \
_Eo_Object *obj; \
do { \
obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
if (!obj) return; \
EO_MAGIC_RETURN((Eo_Header *) obj, EO_EINA_MAGIC); \
} while (0)
#define EO_OBJ_POINTER_GOTO(obj_id, obj, label) \
_Eo_Object *obj; \
do { \
obj = _eo_obj_pointer_get((Eo_Id)obj_id); \
if (!obj || \
!EINA_MAGIC_CHECK((Eo_Header *) obj, EO_EINA_MAGIC)) goto label; \
} while (0)
#define EO_CLASS_POINTER(klass_id, klass) \
_Efl_Class *klass; \
do { \
klass = _eo_class_pointer_get(klass_id); \
if (klass && \
!EINA_MAGIC_CHECK((Eo_Header *) klas, EO_CLASS_EINA_MAGIC)) { \
EO_MAGIC_FAIL((Eo_Header *) klass, EO_CLASS_EINA_MAGIC); \
} \
} while (0)
#define EO_CLASS_POINTER_RETURN_VAL(klass_id, klass, ret) \
_Efl_Class *klass; \
do { \
klass = _eo_class_pointer_get(klass_id); \
if (!klass) return (ret); \
EO_MAGIC_RETURN_VAL((Eo_Header *) klass, EO_CLASS_EINA_MAGIC, ret); \
} while (0)
#define EO_CLASS_POINTER_RETURN(klass_id, klass) \
_Efl_Class *klass; \
do { \
klass = _eo_class_pointer_get(klass_id); \
if (!klass) return; \
EO_MAGIC_RETURN((Eo_Header *) klass, EO_CLASS_EINA_MAGIC); \
} while (0)
#define EO_CLASS_POINTER_GOTO(klass_id, klass, label) \
_Efl_Class *klass; \
do { \
klass = _eo_class_pointer_get(klass_id); \
if (!klass) goto label; \
if (klass && \
!EINA_MAGIC_CHECK((Eo_Header *) klas, EO_CLASS_EINA_MAGIC)) { \
goto label;
} \
} while (0)
#define EO_OBJ_DONE(obj_id)
#endif
#ifdef EFL_DEBUG
void _eo_print();
static inline void _eo_print(Eo_Id_Table_Data *tdata);
#endif
extern Eina_TLS _eo_table_data;

View File

@ -557,6 +557,7 @@ shared_err:
return id;
#else
(void) obj;
(void) parent_id;
return MASK_OBJ_TAG;
#endif
}