GNOME Bugzilla – Bug 701694
mem profiler is unusable after g_type_init deprecation
Last modified: 2015-08-02 01:43:11 UTC
I noticed that a few of IBus test cases, which has "g_mem_set_vtable (glib_mem_profiler_table)", started failing after the g_type_init deprecation. It can be reproduced with the following simple test case: $ cat > test.c <<EOF #include <glib-object.h> static void test_alloc (void) { g_object_new (G_TYPE_OBJECT, NULL); } gint main (gint argc, gchar **argv) { g_mem_set_vtable (glib_mem_profiler_table); g_test_init (&argc, &argv, NULL); g_test_add_func ("/alloc", test_alloc); return g_test_run (); } ^D $ ./test /alloc: *** Error in `./test': realloc(): invalid pointer: 0x000000000084ce80 *** Looking at the valgrind output (attached), Glib seems to call profiler_try_realloc on a memory block allocated by non-profiling malloc (called from gobject_init_ctor).
Created attachment 246127 [details] valgrind log
*** Bug 712295 has been marked as a duplicate of this bug. ***
*** Bug 705303 has been marked as a duplicate of this bug. ***
I ran into this when trying to use libgc with glib (in other words, a non-profiling use of g_mem_set_vtable). The only idea I see for a fix so far, comment #3 of bug 705303, only works for profiling (it suggests reading GOBJECT_DEBUG in gobject_init_ctor. It looks as though it might be possible to work around this by rewiring libc's allocator, where possible: glibc allows this via variables, so presumably the rewiring can be done statically, before gobject_init_ctor is run; however, this solution isn't portable. (libgc has an option to override malloc, but that doesn't work on all platforms (e.g. amd64 Ubuntu!), and it doesn't help other allocators.) While we're waiting for a fix (a way to disable gobject_init_ctor at runtime?), any other suggestions?
I guess one fix would be to use the same mechanism in glib as in glibc, i.e. the ability statically to override the allocator. However, it would also need, at least for libgc, an "init" hook, as libgc needs to be initialised before it can be called.
Or just a hook variable that disables the gobject_init_ctor magic.
Created attachment 274238 [details] [review] Sets glib_mem_profiler_table in gobject_init_ctor() There is a GOBJECT_DEBUG env variable, that is used to debug GType/GObject. I've added one more value to it - "memory", that forces to set glib_mem_profiler_table earily in gobject_init_ctor(). This solution does not allow you to set your own GMemVTable. But you'll be able to call g_mem_profile() and get memory usage summary.
Review of attachment 274238 [details] [review]: I'm not a GLib developer, but I don't think this is correct. Firstly, memory management is handled in libglib, not libgobject, so the g_mem_set_vtable() call should happen in the libglib initialiser function (g_debug_init() in glib-init.c). Secondly, this doesn't restore the original behaviour of supporting custom memory vtables.
The problem is that gobject_init_ctor() is making a memory allocation somewhere, so the options are to: • Change it so it doesn't. • Force the vtable to be set up in glib_init(), as above, which only allows a fixed set of vtables to be used. • Require the user to call g_mem_set_vtable() from their own constructor function which is ordered to be called before glib_init(). The first option is not possible: gobject_init_ctor() is essentially g_type_init(), and we can't change the GLib type system to not perform allocations. The second option is the approach almost taken by this patch. The third option might work, but would require existing calls to g_mem_set_vtable() to be moved to a constructor, and would require G_DEFINE_CONSTRUCTOR() to grow support for ordering invocations of the constructor functions. From some quick research, this looks like it should be possible for all the supported platforms except perhaps SunPro C, which seems to require linker intervention to guarantee constructor/destructor ordering. This option seems fragile to me, but might be workable. Ryan, what do you think about the possibility of enforcing constructor ordering?
Another option is to just deprecate the whole g_mem_set_vtable() thing. We have valgrind now.
Valgrind is fine for debugging, but this API was also used to replace the allocator for other reasons, e.g. to use a garbage collector or use a different allocator for a specific application.
I don't think it is reasonable to make this work. We could possibly make the gobject constructor do some magic, but any other constructor which we don't control could call g_malloc too. And anyway, a full solution would need to handle other libraries calling malloc() directly. Any robust special handling of malloc must happen at the libc level. Thus i think we should just drop the overhead of constatly going through a vtable. Patches for this are in bug 751592.
fwiw, glibc even provides facilities for doing this at the libc level. $ man 3 malloc_hook for more details
*** Bug 752320 has been marked as a duplicate of this bug. ***
Since the patch in bug #751592 landed, this bug is surely WONTFIX...?