LD_PRELOAD GObject lifetime debugging tool

For years and years I’ve dreamt of a tool that would show me what GObjects are currently alive, and let me have a look at information about them. Today, while trying to debug a particularly horrid reference leak (program wedged under refdbg, and without being able to script SIGTRAP I’ve never found this method useful), I actually started writing the tool.

The tool uses LD_PRELOAD to replace g_object_new() — it should really replace g_object_newv() and g_object_new_valist() also, but I didn’t need those — to install a weak reference on the created objects to track their lifetime.

The result of which is something like this:

[danni@adelie src]$ LD_PRELOAD=libgobject-list.so \
    GOBJECT_LIST_FILTER=Gabble GABBLE_PERSIST=1 \
    /usr/lib/telepathy/telepathy-gabble 
 ++ Created object 0x9912530, GabbleGatewayPlugin
 ++ Created object 0x990c460, GabblePluginLoader
 ++ Created object 0x9917ab8, GabbleJabberProtocol
 ++ Created object 0x99172f0, GabbleConnectionManager
...

You can then list the currently living objects and their reference counts by sending SIGUSR1.

[danni@adelie src]$ killall -USR1 telepathy-gabble
Living Objects:
 - 0x9b47038, GabblePresence: 1 refs
 - 0x990c460, GabblePluginLoader: 2 refs
 - 0x9918ae0, GabbleRosterChannel: 1 refs
 - 0x991cb38, GabbleIMChannel: 1 refs
...

This by itself was useful in showing which object wasn’t finalized but should have been (and why my object in question also hadn’t finalized), but didn’t show me who was still holding the reference.

My hunch was that the problem was a reference cycle between two objects, so I hacked a bit of code into my tool to list the “connection” property on all objects that had it. [In Telepathy Connection Managers, objects are typically meant to let this go when connections become disconnected.]

  while (g_hash_table_iter_next (&iter, (gpointer) &obj, NULL))
    {
      GObjectClass *klass;
      GObject *conn;
 
      g_print (" - %p, %s: %u refs\n",
          obj, G_OBJECT_TYPE_NAME (obj), obj->ref_count);
 
      klass = G_OBJECT_GET_CLASS (obj);
      if (g_object_class_find_property (klass, "connection") != NULL)
        {
          g_object_get (obj,
              "connection", &conn,
              NULL);
          g_print ("\t + connection = %p\n", conn);
          if (conn != NULL)
            g_object_unref (conn);
        }
    }

This showed me which object was still holding a ref it should have let go. [Now I just need to work out why, the code in question is in an abstract base class, for which 5 of 6 concrete classes work correctly.]

If you’re interested, the code is in Git.

The tool could still benefit from a lot of work. For instance, the filtering is pretty basic at the moment and it should support all the ways to create GObjects. Originally I had envisioned this tool as a GUI window that popped up, so that you could click on an object and view all of its properties, connected signals, etc. That would be pretty neat actually.

Update: cassidy has already contributed by adding a listing of the objects remaining when a program exits and thus found a leak in Empathy. Awesome!

About Danielle

Danielle is an Australian software engineer, computer scientist and feminist. She has worked on GNOME for some time now. Opinions and writing are solely her own and so not represent her employer, the GNOME Foundation, or anyone else but herself.
This entry was posted in c, collabora, example code, programming, telepathy, work. Bookmark the permalink.

11 Responses to LD_PRELOAD GObject lifetime debugging tool

  1. Eitan says:

    Very cool. I plan to use this one day (likely when a GabbleConnection lingers ;)

  2. xclaesse says:

    This looks awesome, thanks!

    (unfortunately, I’m doing QObject atm…)

  3. Danielle says:

    @alexl: that’s a neat trick. I’ve never looked at SystemTap.

  4. Philip says:

    @Danielle: I found systemtap quite useful when debugging folks, but unless things have changed since the summer, it’s probably still quite a pain to set up on any distro other than Fedora. (iirc, there are still a few kernel patches which need upstreaming.)

  5. alexl says:

    Danielle: The markers are in glib now, so it should be easy to use. At least on fedora.

  6. Stefano Teso says:

    Thanks for the trick. A similar tool is refdbg[1]. The nice thing is that it’s already packaged for debian. :-)

    [1] http://gitorious.org/refdbg/refdbg

  7. daniel says:

    Nice, I actually did pretty much the same thing for debugging the use of libxmmsclient in a Vala-based client:
    http://git.xmms.se/cgit.cgi/xmms2/xmmsrefdbg/tree/xmmsrefdbg.c

    Too bad systemtap support isn’t available in more distros :(

  8. Stefan Kost says:

    Danielle, you know Refdbg? http://www.gitorious.org/refdbg

  9. J├Ârgen says:

    You might want to check this out, when going for a UI: http://chipx86.github.com/gtkparasite/ It’s probably not related to ref-counting, and might be Gtk-only (i.e. not suitable for GObject-only using apps like connection-managers) in it’s current form. But maybe it’s good for inspiration :-)

  10. Danielle says:

    @Stefan and @Stefano: yes, I do know about refdbg, as I said at the top, refdbg was wedging my program. I didn’t try your newer version Stefan, because I didn’t know about it.

Comments are closed.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>