+Sun Feb 4 07:38:32 2001 Tim Janik <timj@gtk.org>
+
+ * docs/debugging.txt: s/glib_trap_/g_trap_/. add comments on
+ g_trap_instance_signals, g_trace_instance_signals and
+ GRUNTIME_DEBUG.
+
+ * gmem.c: s/glib_trap_/g_trap_/.
+
2001-02-04 Tor Lillqvist <tml@iki.fi>
* tests/Makefile.am (thread_LDADD): Change order of libs,
+Sun Feb 4 07:38:32 2001 Tim Janik <timj@gtk.org>
+
+ * docs/debugging.txt: s/glib_trap_/g_trap_/. add comments on
+ g_trap_instance_signals, g_trace_instance_signals and
+ GRUNTIME_DEBUG.
+
+ * gmem.c: s/glib_trap_/g_trap_/.
+
2001-02-04 Tor Lillqvist <tml@iki.fi>
* tests/Makefile.am (thread_LDADD): Change order of libs,
+Sun Feb 4 07:38:32 2001 Tim Janik <timj@gtk.org>
+
+ * docs/debugging.txt: s/glib_trap_/g_trap_/. add comments on
+ g_trap_instance_signals, g_trace_instance_signals and
+ GRUNTIME_DEBUG.
+
+ * gmem.c: s/glib_trap_/g_trap_/.
+
2001-02-04 Tor Lillqvist <tml@iki.fi>
* tests/Makefile.am (thread_LDADD): Change order of libs,
+Sun Feb 4 07:38:32 2001 Tim Janik <timj@gtk.org>
+
+ * docs/debugging.txt: s/glib_trap_/g_trap_/. add comments on
+ g_trap_instance_signals, g_trace_instance_signals and
+ GRUNTIME_DEBUG.
+
+ * gmem.c: s/glib_trap_/g_trap_/.
+
2001-02-04 Tor Lillqvist <tml@iki.fi>
* tests/Makefile.am (thread_LDADD): Change order of libs,
+Sun Feb 4 07:38:32 2001 Tim Janik <timj@gtk.org>
+
+ * docs/debugging.txt: s/glib_trap_/g_trap_/. add comments on
+ g_trap_instance_signals, g_trace_instance_signals and
+ GRUNTIME_DEBUG.
+
+ * gmem.c: s/glib_trap_/g_trap_/.
+
2001-02-04 Tor Lillqvist <tml@iki.fi>
* tests/Makefile.am (thread_LDADD): Change order of libs,
+Sun Feb 4 07:38:32 2001 Tim Janik <timj@gtk.org>
+
+ * docs/debugging.txt: s/glib_trap_/g_trap_/. add comments on
+ g_trap_instance_signals, g_trace_instance_signals and
+ GRUNTIME_DEBUG.
+
+ * gmem.c: s/glib_trap_/g_trap_/.
+
2001-02-04 Tor Lillqvist <tml@iki.fi>
* tests/Makefile.am (thread_LDADD): Change order of libs,
+Sun Feb 4 07:38:32 2001 Tim Janik <timj@gtk.org>
+
+ * docs/debugging.txt: s/glib_trap_/g_trap_/. add comments on
+ g_trap_instance_signals, g_trace_instance_signals and
+ GRUNTIME_DEBUG.
+
+ * gmem.c: s/glib_trap_/g_trap_/.
+
2001-02-04 Tor Lillqvist <tml@iki.fi>
* tests/Makefile.am (thread_LDADD): Change order of libs,
+Sun Feb 4 07:38:32 2001 Tim Janik <timj@gtk.org>
+
+ * docs/debugging.txt: s/glib_trap_/g_trap_/. add comments on
+ g_trap_instance_signals, g_trace_instance_signals and
+ GRUNTIME_DEBUG.
+
+ * gmem.c: s/glib_trap_/g_trap_/.
+
2001-02-04 Tor Lillqvist <tml@iki.fi>
* tests/Makefile.am (thread_LDADD): Change order of libs,
-
-G_BREAKPOINT () traps for the debugger
-======================================
+Traps (G_BREAKPOINT) and traces for the debuging
+================================================
Some code portions contain trap variables that can be set during
debugging time if G_ENABLE_DEBUG has been defined upon compilation
program state and backtrace.
Currently, the following trap variables exist:
-static volatile gulong glib_trap_free_size;
-static volatile gulong glib_trap_realloc_size;
-static volatile gulong glib_trap_malloc_size;
+static volatile gulong g_trap_free_size;
+static volatile gulong g_trap_realloc_size;
+static volatile gulong g_trap_malloc_size;
If set to a size > 0, g_free(), g_realloc() and g_malloc()
respectively, will be intercepted if the size matches the
size of the corresponding memory block to free/reallocate/allocate.
This will only work with g_mem_set_vtable (glib_mem_profiler_table)
upon startup though, because memory profiling is required to match
on the memory block sizes.
-static volatile GObject *glib_trap_object_ref;
+static volatile GObject *g_trap_object_ref;
If set to a valid object pointer, ref/unref will be intercepted
with G_BREAKPOINT ();
+static volatile gpointer *g_trap_instance_signals;
+static volatile gpointer *g_trace_instance_signals;
+ If set to a valid instance pointer, debugging messages
+ will be spewed about emissions of signals on this instance.
+ For g_trap_instance_signals matches, the emissions will
+ also be intercepted with G_BREAKPOINT ();
+
+Environment variables for debugging
+===================================
+When G_ENABLE_DEBUG was defined upon compilation, GRuntime supports
+an environment variable GRUNTIME_DEBUG that can be set to a
+combination of the flags passed in to g_type_init() (currently
+"objects" and "signals") to trigger debugging messages about
+object bookkeeping and signal emissions during runtime.
-2000/12/28 Tim Janik
+2000/02/04 Tim Janik
@param_id:
@pspec:
-<!-- ##### FUNCTION g_param_spec_hash_table_insert ##### -->
+<!-- ##### SECTION ./tmpl/gtypemodule.sgml.sgml:See_Also ##### -->
<para>
</para>
-@hash_table:
-@pspec:
-@owner_type:
-<!-- ##### SECTION ./tmpl/gtypemodule.sgml.sgml:See_Also ##### -->
+<!-- ##### FUNCTION g_param_spec_hash_table_insert ##### -->
<para>
</para>
+@hash_table:
+@pspec:
+@owner_type:
<!-- ##### MACRO G_IS_PARAM_VALUE ##### -->
<para>
@pspec:
@trailer:
+<!-- ##### SECTION ./tmpl/gtypemodule.sgml.sgml:Long_Description ##### -->
+<para>
+
+</para>
+
+
<!-- ##### ENUM GSignalType ##### -->
<para>
@G_SIGNAL_ACTION:
@G_SIGNAL_NO_HOOKS:
-<!-- ##### SECTION ./tmpl/gtypemodule.sgml.sgml:Long_Description ##### -->
-<para>
-
-</para>
-
-
<!-- ##### FUNCTION g_signal_type_closure_new ##### -->
<para>
type implementations or the signal system).
</para>
+@debug_flags:
<!-- ##### FUNCTION g_type_name ##### -->
static gulong profile_mc_frees = 0;
static GMutex *g_profile_mutex = NULL;
#ifdef G_ENABLE_DEBUG
-static volatile gulong glib_trap_free_size = 0;
-static volatile gulong glib_trap_realloc_size = 0;
-static volatile gulong glib_trap_malloc_size = 0;
+static volatile gulong g_trap_free_size = 0;
+static volatile gulong g_trap_realloc_size = 0;
+static volatile gulong g_trap_malloc_size = 0;
#endif /* G_ENABLE_DEBUG */
#define PROFILE_TABLE(f1,f2,f3) ( ( ((f3) << 2) | ((f2) << 1) | (f1) ) * (MEM_PROFILE_TABLE_SIZE + 1))
gulong *p;
#ifdef G_ENABLE_DEBUG
- if (glib_trap_malloc_size == n_bytes)
+ if (g_trap_malloc_size == n_bytes)
G_BREAKPOINT ();
#endif /* G_ENABLE_DEBUG */
gulong *p;
#ifdef G_ENABLE_DEBUG
- if (glib_trap_malloc_size == l)
+ if (g_trap_malloc_size == l)
G_BREAKPOINT ();
#endif /* G_ENABLE_DEBUG */
else
{
#ifdef G_ENABLE_DEBUG
- if (glib_trap_free_size == p[1])
+ if (g_trap_free_size == p[1])
G_BREAKPOINT ();
#endif /* G_ENABLE_DEBUG */
p -= 2;
#ifdef G_ENABLE_DEBUG
- if (glib_trap_realloc_size == n_bytes)
+ if (g_trap_realloc_size == n_bytes)
G_BREAKPOINT ();
#endif /* G_ENABLE_DEBUG */
static gulong profile_mc_frees = 0;
static GMutex *g_profile_mutex = NULL;
#ifdef G_ENABLE_DEBUG
-static volatile gulong glib_trap_free_size = 0;
-static volatile gulong glib_trap_realloc_size = 0;
-static volatile gulong glib_trap_malloc_size = 0;
+static volatile gulong g_trap_free_size = 0;
+static volatile gulong g_trap_realloc_size = 0;
+static volatile gulong g_trap_malloc_size = 0;
#endif /* G_ENABLE_DEBUG */
#define PROFILE_TABLE(f1,f2,f3) ( ( ((f3) << 2) | ((f2) << 1) | (f1) ) * (MEM_PROFILE_TABLE_SIZE + 1))
gulong *p;
#ifdef G_ENABLE_DEBUG
- if (glib_trap_malloc_size == n_bytes)
+ if (g_trap_malloc_size == n_bytes)
G_BREAKPOINT ();
#endif /* G_ENABLE_DEBUG */
gulong *p;
#ifdef G_ENABLE_DEBUG
- if (glib_trap_malloc_size == l)
+ if (g_trap_malloc_size == l)
G_BREAKPOINT ();
#endif /* G_ENABLE_DEBUG */
else
{
#ifdef G_ENABLE_DEBUG
- if (glib_trap_free_size == p[1])
+ if (g_trap_free_size == p[1])
G_BREAKPOINT ();
#endif /* G_ENABLE_DEBUG */
p -= 2;
#ifdef G_ENABLE_DEBUG
- if (glib_trap_realloc_size == n_bytes)
+ if (g_trap_realloc_size == n_bytes)
G_BREAKPOINT ();
#endif /* G_ENABLE_DEBUG */
+Sun Feb 4 07:30:53 2001 Tim Janik <timj@gtk.org>
+
+ * gtype.[hc]: changed g_type_init() to take debugging flags
+ initially, a combination of G_TYPE_DEBUG_OBJECTS and
+ G_TYPE_DEBUG_SIGNALS. using the G_TYPE_ prefix is a bit odd
+ here, but basically g_type_int() serves as initialization
+ fucntion for all of GType, GObject, GSignal, so what the heck.
+
+ * gobject.c: special case debugging code properly.
+ changed glib_trap_object_ref to g_trap_object_ref.
+
+ * gsignal.c: add signal emission debugging abilities, along with
+ a new trap object g_trap_instance_signals.
+
2001-02-04 Tor Lillqvist <tml@iki.fi>
* Makefile.am (progs_LDADD): Change order of libs to libgobject
f_out = stdout;
- g_type_init ();
+ g_type_init (0);
root = G_TYPE_OBJECT;
/* --- functions --- */
-/* We need an actual method for handling debug keys in GLib.
- * For now, we'll simply use, as a method
- * 'extern gboolean glib_debug_objects'
- */
-gboolean glib_debug_objects = FALSE;
-
#ifdef G_ENABLE_DEBUG
+#define IF_DEBUG(debug_type) if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type)
G_LOCK_DEFINE_STATIC (debug_objects);
-static volatile GObject *glib_trap_object_ref = NULL;
+static volatile GObject *g_trap_object_ref = NULL;
static guint debug_objects_count = 0;
static GHashTable *debug_objects_ht = NULL;
static void
gpointer user_data)
{
GObject *object = value;
-
+
g_message ("[%p] stale %s\tref_count=%u",
object,
G_OBJECT_TYPE_NAME (object),
static void
debug_objects_atexit (void)
{
- G_LOCK (debug_objects);
- if (glib_debug_objects)
+ IF_DEBUG (OBJECTS)
{
+ G_LOCK (debug_objects);
if (debug_objects_ht)
{
g_message ("stale GObjects: %u", debug_objects_count);
g_hash_table_foreach (debug_objects_ht, debug_objects_foreach, NULL);
}
+ G_UNLOCK (debug_objects);
}
- G_UNLOCK (debug_objects);
}
-#endif /* G_ENABLE_DEBUG */
+#endif /* G_ENABLE_DEBUG */
void
g_object_type_init (void) /* sync with gtype.c */
g_assert (type == G_TYPE_OBJECT);
#ifdef G_ENABLE_DEBUG
- g_atexit (debug_objects_atexit);
+ IF_DEBUG (OBJECTS)
+ g_atexit (debug_objects_atexit);
#endif /* G_ENABLE_DEBUG */
}
/* freeze object's notification queue, g_object_new_valist() takes care of that */
object_freeze_notifies (object);
-
+
#ifdef G_ENABLE_DEBUG
- G_LOCK (debug_objects);
- if (glib_debug_objects)
+ IF_DEBUG (OBJECTS)
{
+ G_LOCK (debug_objects);
if (!debug_objects_ht)
debug_objects_ht = g_hash_table_new (g_direct_hash, NULL);
debug_objects_count++;
g_hash_table_insert (debug_objects_ht, object, object);
+ G_UNLOCK (debug_objects);
}
- G_UNLOCK (debug_objects);
#endif /* G_ENABLE_DEBUG */
}
G_OBJECT_GET_CLASS (object)->shutdown (object);
#ifdef G_ENABLE_DEBUG
- if (glib_trap_object_ref == object)
+ if (g_trap_object_ref == object)
G_BREAKPOINT ();
#endif /* G_ENABLE_DEBUG */
{
G_OBJECT_GET_CLASS (object)->finalize (object);
#ifdef G_ENABLE_DEBUG
- G_LOCK (debug_objects);
- if (glib_debug_objects && debug_objects_ht)
- g_assert (g_hash_table_lookup (debug_objects_ht, object) == NULL);
- G_UNLOCK (debug_objects);
+ IF_DEBUG (OBJECTS)
+ {
+ G_LOCK (debug_objects);
+ if (debug_objects_ht)
+ g_assert (g_hash_table_lookup (debug_objects_ht, object) == NULL);
+ G_UNLOCK (debug_objects);
+ }
#endif /* G_ENABLE_DEBUG */
g_type_free_instance ((GTypeInstance*) object);
}
g_datalist_clear (&object->qdata);
#ifdef G_ENABLE_DEBUG
- G_LOCK (debug_objects);
- if (glib_debug_objects)
+ IF_DEBUG (OBJECTS)
{
+ G_LOCK (debug_objects);
g_assert (g_hash_table_lookup (debug_objects_ht, object) == object);
-
g_hash_table_remove (debug_objects_ht, object);
debug_objects_count--;
+ G_UNLOCK (debug_objects);
}
- G_UNLOCK (debug_objects);
#endif /* G_ENABLE_DEBUG */
}
g_return_val_if_fail (object->ref_count > 0, NULL);
#ifdef G_ENABLE_DEBUG
- if (glib_trap_object_ref == object)
+ if (g_trap_object_ref == object)
G_BREAKPOINT ();
#endif /* G_ENABLE_DEBUG */
g_return_if_fail (object->ref_count > 0);
#ifdef G_ENABLE_DEBUG
- if (glib_trap_object_ref == object)
+ if (g_trap_object_ref == object)
G_BREAKPOINT ();
#endif /* G_ENABLE_DEBUG */
#define EMISSION_PRE_ALLOC (16)
#define REPORT_BUG "please report occourance circumstances to gtk-devel-list@gnome.org"
+#ifdef G_ENABLE_DEBUG
+#define IF_DEBUG(debug_type, cond) if ((_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) || cond)
+static volatile gpointer *g_trace_instance_signals = NULL;
+static volatile gpointer *g_trap_instance_signals = NULL;
+#endif /* G_ENABLE_DEBUG */
/* --- generic allocation --- */
guint signal_id = node->signal_id;
gboolean return_value_altered = FALSE;
+#ifdef G_ENABLE_DEBUG
+ IF_DEBUG (SIGNALS, g_trace_instance_signals == instance || g_trap_instance_signals == instance)
+ {
+ g_message ("%s::%s(%u) emitted (instance=%p signal-node=%p)\n",
+ g_type_name (G_TYPE_FROM_INSTANCE (instance)),
+ node->name, detail,
+ instance, node);
+ if (g_trap_instance_signals == instance)
+ G_BREAKPOINT ();
+ }
+#endif /* G_ENABLE_DEBUG */
+
if (node->flags & G_SIGNAL_NO_RECURSE)
{
Emission *emission = emission_find (g_restart_emissions, signal_id, detail, instance);
else \
g_error ("%s()%s`%s'", _fname, _action, _tname); \
}G_STMT_END
+#ifdef G_ENABLE_DEBUG
+#define DEBUG_CODE(debug_type, code_block) G_STMT_START { \
+ if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) \
+ { code_block; } \
+} G_STMT_END
+#else /* !G_ENABLE_DEBUG */
+#define DEBUG_CODE(debug_type, code_block) /* code_block */
+#endif /* G_ENABLE_DEBUG */
#define TYPE_FUNDAMENTAL_FLAG_MASK (G_TYPE_FLAG_CLASSED | \
G_TYPE_FLAG_INSTANTIATABLE | \
static ClassCacheFunc *static_class_cache_funcs = NULL;
static GType static_last_fundamental_id = 0;
static GQuark static_quark_type_flags = 0;
+GTypeDebugFlags _g_type_debug_flags = 0;
/* --- externs --- */
/* --- initialization --- */
void
-g_type_init (void)
+g_type_init (GTypeDebugFlags debug_flags)
{
G_LOCK_DEFINE_STATIC (type_init_lock);
static TypeNode *type0_node = NULL;
+ gchar *env_string;
GTypeInfo info;
TypeNode *node;
GType type;
G_UNLOCK (type_init_lock);
return;
}
+
+ /* setup GRuntime wide debugging flags */
+ _g_type_debug_flags = debug_flags & G_TYPE_DEBUG_MASK;
+ env_string = g_getenv ("GRUNTIME_DEBUG");
+ if (env_string != NULL)
+ {
+ static GDebugKey debug_keys[] = {
+ { "objects", G_TYPE_DEBUG_OBJECTS },
+ { "signals", G_TYPE_DEBUG_SIGNALS },
+ };
+
+ _g_type_debug_flags |= g_parse_debug_string (env_string,
+ debug_keys,
+ sizeof (debug_keys) / sizeof (debug_keys[0]));
+ env_string = NULL;
+ }
/* quarks */
static_quark_type_flags = g_quark_from_static_string ("GTypeFlags");
#define G_TYPE_FROM_INTERFACE(g_iface) (((GTypeInterface*) (g_iface))->g_type)
+/* debug flags for g_type_init() */
+typedef enum /*< skip >*/
+{
+ G_TYPE_DEBUG_OBJECTS = 1 << 0,
+ G_TYPE_DEBUG_SIGNALS = 1 << 1,
+ G_TYPE_DEBUG_MASK = 0x03
+} GTypeDebugFlags;
+
+
/* --- prototypes --- */
-void g_type_init (void);
+void g_type_init (GTypeDebugFlags debug_flags);
gchar* g_type_name (GType type);
GQuark g_type_qname (GType type);
GType g_type_from_name (const gchar *name);
GTypeValueTable* g_type_value_table_peek (GType type);
+/* --- implementation bits --- */
#ifndef G_DISABLE_CAST_CHECKS
# define _G_TYPE_CIC(ip, gt, ct) \
((ct*) g_type_check_instance_cast ((GTypeInstance*) ip, gt))
#define _G_TYPE_IGC(ip, gt, ct) ((ct*) (((GTypeInstance*) ip)->g_class))
#define _G_TYPE_IGI(ip, gt, ct) ((ct*) g_type_interface_peek (((GTypeInstance*) ip)->g_class, gt))
#define G_TYPE_FLAG_RESERVED_ID_BIT (1 << 30)
+extern GTypeDebugFlags _g_type_debug_flags;
#ifdef __cplusplus