diff --git a/ChangeLog b/ChangeLog index 4d0cc4c67..4dd323f33 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +Sun Feb 4 07:38:32 2001 Tim Janik + + * 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 * tests/Makefile.am (thread_LDADD): Change order of libs, diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 4d0cc4c67..4dd323f33 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,11 @@ +Sun Feb 4 07:38:32 2001 Tim Janik + + * 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 * tests/Makefile.am (thread_LDADD): Change order of libs, diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 4d0cc4c67..4dd323f33 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,11 @@ +Sun Feb 4 07:38:32 2001 Tim Janik + + * 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 * tests/Makefile.am (thread_LDADD): Change order of libs, diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index 4d0cc4c67..4dd323f33 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,3 +1,11 @@ +Sun Feb 4 07:38:32 2001 Tim Janik + + * 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 * tests/Makefile.am (thread_LDADD): Change order of libs, diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 4d0cc4c67..4dd323f33 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,11 @@ +Sun Feb 4 07:38:32 2001 Tim Janik + + * 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 * tests/Makefile.am (thread_LDADD): Change order of libs, diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 4d0cc4c67..4dd323f33 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,11 @@ +Sun Feb 4 07:38:32 2001 Tim Janik + + * 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 * tests/Makefile.am (thread_LDADD): Change order of libs, diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 4d0cc4c67..4dd323f33 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,11 @@ +Sun Feb 4 07:38:32 2001 Tim Janik + + * 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 * tests/Makefile.am (thread_LDADD): Change order of libs, diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 4d0cc4c67..4dd323f33 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,11 @@ +Sun Feb 4 07:38:32 2001 Tim Janik + + * 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 * tests/Makefile.am (thread_LDADD): Change order of libs, diff --git a/docs/debugging.txt b/docs/debugging.txt index 6f3bca1cc..abef4dd1b 100644 --- a/docs/debugging.txt +++ b/docs/debugging.txt @@ -1,7 +1,6 @@ - -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 @@ -11,18 +10,32 @@ Such traps lead to immediate code halts to examine the current 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 diff --git a/docs/reference/gobject/tmpl/gobject-unused.sgml b/docs/reference/gobject/tmpl/gobject-unused.sgml index 9372f183f..4a51ebefb 100644 --- a/docs/reference/gobject/tmpl/gobject-unused.sgml +++ b/docs/reference/gobject/tmpl/gobject-unused.sgml @@ -16,6 +16,12 @@ @param_id: @pspec: + + + + + + @@ -25,12 +31,6 @@ @pspec: @owner_type: - - - - - - @@ -84,6 +84,12 @@ @pspec: @trailer: + + + + + + @@ -96,12 +102,6 @@ @G_SIGNAL_ACTION: @G_SIGNAL_NO_HOOKS: - - - - - - diff --git a/docs/reference/gobject/tmpl/types.sgml b/docs/reference/gobject/tmpl/types.sgml index 3994dd5a4..3c9e3abdb 100644 --- a/docs/reference/gobject/tmpl/types.sgml +++ b/docs/reference/gobject/tmpl/types.sgml @@ -398,6 +398,7 @@ the type system and assorted other code portions (such as the various fundamenta type implementations or the signal system). +@debug_flags: diff --git a/glib/gmem.c b/glib/gmem.c index bcdc7fcfc..52d376530 100644 --- a/glib/gmem.c +++ b/glib/gmem.c @@ -268,9 +268,9 @@ static gulong profile_frees = 0; 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)) @@ -404,7 +404,7 @@ profiler_try_malloc (gsize n_bytes) 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 */ @@ -442,7 +442,7 @@ profiler_calloc (gsize n_blocks, gulong *p; #ifdef G_ENABLE_DEBUG - if (glib_trap_malloc_size == l) + if (g_trap_malloc_size == l) G_BREAKPOINT (); #endif /* G_ENABLE_DEBUG */ @@ -480,7 +480,7 @@ profiler_free (gpointer mem) 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 */ @@ -506,7 +506,7 @@ profiler_try_realloc (gpointer mem, 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 */ diff --git a/gmem.c b/gmem.c index bcdc7fcfc..52d376530 100644 --- a/gmem.c +++ b/gmem.c @@ -268,9 +268,9 @@ static gulong profile_frees = 0; 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)) @@ -404,7 +404,7 @@ profiler_try_malloc (gsize n_bytes) 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 */ @@ -442,7 +442,7 @@ profiler_calloc (gsize n_blocks, gulong *p; #ifdef G_ENABLE_DEBUG - if (glib_trap_malloc_size == l) + if (g_trap_malloc_size == l) G_BREAKPOINT (); #endif /* G_ENABLE_DEBUG */ @@ -480,7 +480,7 @@ profiler_free (gpointer mem) 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 */ @@ -506,7 +506,7 @@ profiler_try_realloc (gpointer mem, 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 */ diff --git a/gobject/ChangeLog b/gobject/ChangeLog index a0bbcb26f..e948297d4 100644 --- a/gobject/ChangeLog +++ b/gobject/ChangeLog @@ -1,3 +1,17 @@ +Sun Feb 4 07:30:53 2001 Tim Janik + + * 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 * Makefile.am (progs_LDADD): Change order of libs to libgobject diff --git a/gobject/gobject-query.c b/gobject/gobject-query.c index b80709adc..8a440db3a 100644 --- a/gobject/gobject-query.c +++ b/gobject/gobject-query.c @@ -126,7 +126,7 @@ main (gint argc, f_out = stdout; - g_type_init (); + g_type_init (0); root = G_TYPE_OBJECT; diff --git a/gobject/gobject.c b/gobject/gobject.c index 916996da7..b105133f6 100644 --- a/gobject/gobject.c +++ b/gobject/gobject.c @@ -138,15 +138,10 @@ static gulong gobject_signals[LAST_SIGNAL] = { 0, }; /* --- 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 @@ -155,7 +150,7 @@ debug_objects_foreach (gpointer key, gpointer user_data) { GObject *object = value; - + g_message ("[%p] stale %s\tref_count=%u", object, G_OBJECT_TYPE_NAME (object), @@ -164,18 +159,18 @@ debug_objects_foreach (gpointer key, 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 */ @@ -218,7 +213,8 @@ 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 */ } @@ -439,17 +435,17 @@ g_object_init (GObject *object) /* 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 */ } @@ -522,7 +518,7 @@ g_object_last_unref (GObject *object) 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 */ @@ -532,10 +528,13 @@ g_object_last_unref (GObject *object) { 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); } @@ -557,15 +556,14 @@ g_object_finalize (GObject *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 */ } @@ -1243,7 +1241,7 @@ g_object_ref (gpointer _object) 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 */ @@ -1261,7 +1259,7 @@ g_object_unref (gpointer _object) 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 */ diff --git a/gobject/gsignal.c b/gobject/gsignal.c index c251670d9..827f64014 100644 --- a/gobject/gsignal.c +++ b/gobject/gsignal.c @@ -38,6 +38,11 @@ #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 --- */ @@ -1743,6 +1748,18 @@ signal_emit_R (SignalNode *node, 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); diff --git a/gobject/gtype.c b/gobject/gtype.c index 6aaa94b09..dd7482871 100644 --- a/gobject/gtype.c +++ b/gobject/gtype.c @@ -69,6 +69,14 @@ static GStaticRWLock type_rw_lock = G_STATIC_RW_LOCK_INIT; 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 | \ @@ -202,6 +210,7 @@ static guint static_n_class_cache_funcs = 0; 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 --- */ @@ -2354,10 +2363,11 @@ extern void g_signal_init (void); /* sync with gsignal.c */ /* --- 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; @@ -2372,6 +2382,22 @@ g_type_init (void) 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"); diff --git a/gobject/gtype.h b/gobject/gtype.h index 5e0a18283..2e318b99e 100644 --- a/gobject/gtype.h +++ b/gobject/gtype.h @@ -168,8 +168,17 @@ struct _GTypeInterface #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); @@ -328,6 +337,7 @@ gboolean g_type_value_is_a (GValue *value, 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)) @@ -345,6 +355,7 @@ GTypeValueTable* g_type_value_table_peek (GType type); #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