#include "e_error_intern.h"
#include "e_utils.h"
-/* yes - i know. glibc specific... but i like being able to do my own */
-/* backtraces! NB: you need CFLAGS="-rdynamic -g" LDFLAGS="-rdynamic -g" */
-#ifdef OBJECT_PARANOIA_CHECK
-
-/* local subsystem functions */
-static void _e_object_segv(int sig);
-
-/* local subsystem globals */
-static sigjmp_buf _e_object_segv_buf;
-#endif
-
#ifdef OBJECT_HASH_CHECK
E_API Eina_Bool e_obj_hash_check = EINA_FALSE;
E_API Eina_Hash *e_obj_hash = NULL;
E_API int
e_object_error(E_Object *obj)
{
-#ifdef OBJECT_PARANOIA_CHECK
- char buf[4096];
- char bt[8192];
- void *trace[128];
- char **messages = NULL;
- int i, trace_num;
-
- /* fetch stacktrace */
- trace_num = backtrace(trace, 128);
- messages = backtrace_symbols(trace, trace_num);
-
- /* build stacktrace */
- bt[0] = 0;
- if (messages)
- {
- for (i = 1; i < trace_num; i++)
- {
- strcat(bt, messages[i]);
- strcat(bt, "\n");
- }
- free(messages);
- }
- /* if NULL obj then dump stacktrace */
- if (!obj)
- {
- snprintf(buf, sizeof(buf),
- "Object is NULL.\n"
- "%s",
- bt);
- }
- /* if obj pointer is non NULL, actually try an access and see if we segv */
- else if (obj)
- {
- struct sigaction act, oact;
- int magic = 0, segv = 0;
-
- /* setup segv handler */
- act.sa_handler = _e_object_segv;
- act.sa_flags = SA_RESETHAND;
- sigemptyset(&act.sa_mask);
- sigaction(SIGSEGV, &act, &oact);
- /* set a longjump to be within this if statement. only called if we */
- /* segfault */
- if (sigsetjmp(_e_object_segv_buf, 1))
- {
- sigaction(SIGSEGV, &oact, NULL);
- segv = 1;
- }
- else
- {
- /* try access magic value */
- magic = obj->magic;
- /* if pointer is bogus we'd segv and so jump to the if () above */
- /* contents, and thus reset segv handler and set segv flag. */
- /* if not we just continue moving along here and reset handler */
- sigaction(SIGSEGV, &oact, NULL);
- }
- /* if we segfaulted above... */
- if (segv)
- snprintf(buf, sizeof(buf),
- "Object [%p] is an invalid/garbage pointer.\n"
- "Segfault successfully avoided.\n"
- "%s",
- obj,
- bt);
- else
- {
- /* valid ram then... if we freed this object before */
- if (magic == E_OBJECT_MAGIC_FREED)
- snprintf(buf, sizeof(buf),
- "Object [%p] is already freed.\n"
- "%s",
- obj,
- bt);
- /* garbage magic value - pointer to non object */
- else if (magic != E_OBJECT_MAGIC)
- snprintf(buf, sizeof(buf),
- "Object [%p] has garbage magic (%x).\n"
- "%s",
- obj, magic,
- bt);
- else if (obj->references < 0)
- snprintf(buf, sizeof(buf),
- "Object [%p] has negative references (%i).\n"
- "%s",
- obj, obj->references,
- bt);
- else if (obj->references > 100)
- snprintf(buf, sizeof(buf),
- "Object [%p] has unusually high reference count (%i).\n"
- "%s",
- obj, obj->references,
- bt);
- /* it's all ok! */
- else
- {
- return 0;
- }
- }
- }
- /* display actual error message */
- e_error_message_show("%s", buf);
- return 1;
-#else
if (!obj)
{
fprintf(stderr, "ERROR: Object is NULL. Add break point at %s:%d\n",
return 1;
}
return 0;
-#endif
}
E_API void
E_FREE_FUNC(e_obj_hash, eina_hash_free);
}
#endif
-
-#ifdef OBJECT_PARANOIA_CHECK
-/* local subsystem functions */
-static void
-_e_object_segv(int sig)
-{
- siglongjmp(_e_object_segv_buf, 1);
-}
-
-#endif
#include <Eina.h>
#include <Ecore.h>
-/* Object safety/debugging checks */
-/* */
-/* OBJECT_PARANOIA_CHECK is paranoid and checks pointers and traps segv's */
-/* in case they dont work... very paranoid and slow. NB for backtrace to */
-/* work you need gcc, glibc and you need to compile with compile options of */
-/* -g -rdynamic and link with them too */
-/* OBJECT_CHECK is a simple null pointer and magic number check with no */
-/* debug output */
-
-#ifndef __GLIBC__
-# ifdef OBJECT_PARANOIA_CHECK
-# warning "Your system doesn't have glibc. Paranoid object checking disabled."
-# undef OBJECT_PARANOIA_CHECK
-# endif
-#endif
-
#define E_OBJECT_MAGIC 0xe0b9ec75
#define E_OBJECT_MAGIC_FREED 0xe0bf6eed
#define E_OBJECT(x) ((E_Object *)(x))
# define E_OBJECT_HASH_FIND(x) e_object_hash_find(E_OBJECT(x))
#endif
-#ifdef OBJECT_PARANOIA_CHECK
-# define E_OBJECT_CHECK(x) do {if (e_object_error(E_OBJECT(x))) return;} while (0)
-# define E_OBJECT_CHECK_RETURN(x, ret) do {if (e_object_error(E_OBJECT(x))) return ret;} while (0)
-# define E_OBJECT_TYPE_CHECK(x, tp) do {if ((E_OBJECT(x)->type) != (tp)) { CRI("Object type check failed in %s", __FUNCTION__); return;} } while (0)
-# define E_OBJECT_TYPE_CHECK_RETURN(x, tp, ret) do {if ((E_OBJECT(x)->type) != tp) { CRI("Object type check failed in %s", __FUNCTION__); return ret;} } while (0)
-# define E_OBJECT_IF_NOT_TYPE(x, tp) if (E_OBJECT(x)->type != (tp))
-#else
# ifdef OBJECT_CHECK
# ifdef OBJECT_HASH_CHECK
# define E_OBJECT_CHECK(x) \
# define E_OBJECT_TYPE_CHECK_RETURN(x, type, ret)
# define E_OBJECT_IF_NOT_TYPE(x, type)
# endif
-#endif
typedef struct _E_Object_Delfn E_Object_Delfn;