Re: the pros of gtk_debug_shutdown



On Fri, 9 Nov 2001, Michael Meeks wrote:

> 
> Here are some of the pros and cons of having a _debug_shutdown method:
> 
> 	Just to say to start with that I propose a purely optional
> shutdown method. It needs to be a method, since it is nice to return
> non 0 from a regression test when something fails - eg. a leak.
> 
> Pro:
> 	* trivialy allows a library to be tested for leaks
> 	* adds no overhead for the common case

this does indeed add quite some overhead for the common case. so much
that i don't consider it implementing for many of my code portions.
to give a few examples:
- GQuark, in order to free all its strings, would have to keep a list
  about what strings it actually duplicated and which ones it got static
- the type system, and the skeletons of the signal system. the memory
  patterns i'm using there are quite specifically choosen in alloc-only
  manner to reduce complexity, as well as memory and speed overhead.
  (the parts that are possibly unloadable are of course finalizable,
  e.g. the part of a type node that keeps class/instance initialization
  functions, or a major portion of a signal node).
- trashstack using code or similar code portions do:
  
  static inline gpointer
  g_generic_node_alloc (GTrashStack **trash_stack_p,
                        guint         sizeof_node,
                        guint         nodes_pre_alloc)
  {
    gpointer node = g_trash_stack_pop (trash_stack_p);

    if (!node)
      {
        guint8 *block;

        nodes_pre_alloc = MAX (nodes_pre_alloc, 1);
        block = g_malloc (sizeof_node * nodes_pre_alloc);
        while (--nodes_pre_alloc)
          {
            g_trash_stack_push (trash_stack_p, block);
            block += sizeof_node;
          }
        node = block;
      }

    return node;
  }
  #define g_generic_node_free(trash_stack_p, node) g_trash_stack_push (trash_stack_p, node)
  
  i.e., they implement their own alloc-only behaviour in a far more
  efficient manner (speed and memory wise) than memchunks do. not only
  would it be a huge amount of work to alter all those code portions,
  for the example at hand it'd even defeat the original intend which lead
  to not going for a memchunk.
- widget classes. gtk_type_class() might be a good example, regardless of
  how a user registered a type (static or dynamic), once he calls
  gtk_type_class() on it, it's forced to be static by adding refcounts
  and forgetting about them. hm, actually the code there is a bit more
  clever than that, so this might as well be a bad example, the point i
  meant to bring across is code portions that do "heh, i _know_ i want/
  need this to be static, so i can just do <foomagic> and forget about
  it, because i know i do not need to clean up".

> 	* not an atexit method
> 	* allows fully automated - leak checking on distchecl
> 	* allows very frequent leak checking by developers
> 	* stackable - thus gtk+ would shutdown itself, then pango,
> 	  then glib, involving a single method call at 'main' exit:
> 		return gtk_debug_shutdown ();

huh, there're exactly *0* things you can do after you've torn down
your program like that. anything glib, say g_malloc() or g_print() would
instantly segfault on you. (and of course, code portions that do currently
install atexit() handlers will definitely break).

as an aside, i betcha, that if we introduced real shutdown functions, we'll
get a lot of user requests ala:

	Hello, my name is @foouser   I've been doing some gtk programming
	recently and i encountered a problem with initialization.
	Once i temporarily shutdown my program with
	  gtk_shutdown_no_resurrect_dont_use_this();
	i fail to get it reinitialized. For some reason gtk_init() will
	not work after this, is this a bug or have i overlooked some
	gtk_reinit_after_shutdown_if_you_know_better();
	function?

replace @foouser@ with your favourite "Joe [never reading the FAQ] Dude"
username.

> 	* unambiguous the '_debug_shutdown' makes the method's
> 	  purpose quite clear.
> 	* could be used inside Gtk+ to verify ref counting correctness.

you've just seen the stale object hashtable dump at the end of a program
right?
it'd probably be a good idea to add those for other refcounted things as
well, what comes to mind are:
- dynamic classes/interfaces
- closures (huh, i really gotta watch this sometime)
- param specs
- still some pango structures?

> Con:
> 	* adds a new public method, and possibly some internal ones.
> 	* all static / cached GObject resources have to be freed
> 	  by explicit code - not too tough, since we know where they
> 	  all are.
> 	* shutting down modules might be more complex (unlikely)
> 	* requires some maintenance - when you add new global members.
> 
> 	So ...
> 
> 	Can someone possibly explain to me why this would be a bad
> thing ? yes it will involve some work - I am very happy to do that
> work and maintain it; I ask only the entry points to make it possible
> for now.

i hope i could bring across a few of the points on why i'm not very
comfortable with some of the points you raised.

> 	Please - as pro 1 says, it would _really_ help me find leaks,
> and be so much more confidant about library code that is shipped -
> that it is verified as good as it can be - automaticaly.

i do think you have a basic point though, and we definitely need to
do some leak checking, and for that, automation is badly required.
the things i'm thinking about are not as radical though, i.e. i'd
like to see:

- a function glib/gdk/gtk _blow_caches() that blows internal object/memory
  caches where this can be implemented without additional complexity or
  track keeping. this would not cause the program to enter an invalid
  (shutdown) state though, it'd even be usefull for out-of-mem situations
  on embedded devices.
- a facility to tell the program:
  1) at this point, all the static portions should be setup already and
     the caches probably contain enough freespace without needing more
     system allocs in the near future, so start memory track keeping now.
  2) stop track keeping, gimme stats about remaining allocations since
     (1) with caller stacks etc.
  this could e.g. be done via SIGUSR2 and g_mem_set_vtable(), plus some
  backtrace magic (like in http://www.gtk.org/~timj/toyprof-0.1.tar.gz),
  or by improving memprof cleverness somewhat.
  (the GMemVTable approach has the advantage, that this could be used
  as basic framework for a bunch of automated leak checking tests)
- i would have liked to be able to flag static mallocs or static objects
  as such, so debugging magic could tell them apart from normal allocations.
  however, this idea didn't receive much positive response back when we
  discussed GMemVTable last year, mostly because it can't be persued
  pervasively (think g_strdup_static() in singletons).

> 
> 	Thanks for listening,
> 
> 		Michael.
> 

---
ciaoTJ




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]