Category Archives: GNOME

How to waste an evening debugging the internals of glib’s qsort implementation

Working on a personal itch-scratching project, I found myself wanting a sortable treeview. So I stuffed my treemodel into a TreeModelSort and set up my sort functions, and everything was happy. Except, when running my application, I kept getting strange segfaults within glib’s qsort implementation. I had set the following function as my sort_func (yes, it’s C++, but it should be fairly self-explanatory):

static int
compare_foo (const Gtk::TreeModel::iterator& a, const Gtk::TreeModel::iterator& b)
{
    std::tr1::shared_ptr<Foo> l1, l2;
    l1 = a->get_value (COLUMN_FOO);
    l2 = b->get_value (COLUMN_FOO);

    if (!l1)
        return -1;

    if (!l2)
        return 1;

    return l1->get_id () - l2->get_id ();
}

Can you spot the error? Running it under valgrind indicated that I was reading data from *before* the start of the array that was being sorted. In fact, the following lines of code in g_qsort_with_data() were causing tmp_ptr to be decreased back past the start of the array:

        while ((*compare_func) ((void *) run_ptr, (void *) tmp_ptr, user_data) < 0)
          tmp_ptr -= size;

Hmm. Why is there no guard to prevent tmp_ptr from being decreased past the start? Then I noticed the following comment up a few lines:

    /* Find smallest element in first threshold and place it at the
       array's beginning.  This is the smallest array element,
       and the operation speeds up insertion sort's inner loop. */

So at this point, the code is assuming that the very first element of the array is the smallest, so compare_func should always return >= 0 when it reaches the start of the array. Aha! So the problem is my compare_func. It turns out I forgot to handle the single case of both values being NULL.

    l1 = a->get_value (COLUMN_FOO);
    l2 = b->get_value (COLUMN_FOO);
+
+   if (!l1 && !l2)
+       return 0;

    if (!l1)
        return -1;

So there’s not really a big lesson to be learned here, but if you ever hit strange segfaults deep inside glib’s qsort while sorting a treemodel, do yourself a favor and double-check that your sort function is sane first. Also, do yourself a favor and run it under valgrind as soon as you get a strange segfault. Knowing the exact point of the invalid read is infinitely more helpful than waiting until that invalid read causes a segfault.

Pools, Toy Dogs, Turkey, and WebKit

Summer is coming on full force.  R has discovered a new obsession, this time with the pool.  This goes along with her existing obsessions with fish, ducks, and geese.  I’m noticing a pattern here.  She also enjoys non-aquatic things, particularly books — mostly books about animals.  J got an old picture book about Dogs from a garage sale down the block recently.  It’s obviously from another time, as it contains the following hilariously inappropriate line:

Toy DogsThe Toy Dogs today are bred solely as pets. They have no other purpose in life except to give pleasure, especially to ladies.

Also, I’ll be attending GUADEC for the first time this year, and I’m looking forward to a good time in Istanbul and finally meeting a lot of people in person that I’ve known online for a while.

WebKit work is going quite well. I’ve mostly been focusing on bug fixing so far, though I’ve added some new features as well (CSS text shadows are now supported in the Qt port, for instance). Overall I’ve been really impressed with how clean and well-organized WebKit is for such a large and complex project. I’ve also started playing around with ‘webkitmm’ in my spare time as well. Nothing much to show at the moment, I’m afraid, but I don’t expect it to take too much effort before it’s relatively usable.

Feeling Productive

All the recent talk about tetris and canvases and animation prompted me to pick up the C++ bindings for clutter again and play around with it. I’ve added support for the clutter-cairo library and ported the ‘flowers’ demo to cluttermm.

cluttermm-flowers

I’ve also spent some time in the past week adding a marginally useful feature to nemiver: highlighting memory values when they’ve changed since the last time the debugger stopped. Adding this functionality required some significant modifications to the shared GtkHex widget that we use, so it’s not checked into svn yet, but hopefully will be soon. I’m not sure how people did significant refactorings and API additions before tools like git-svn were available. It’s so nice to be able to try out different things and make changes locally with full version control support instead of trying to maintain a mega-patch or committing half-baked ideas to the central repository.

I also released a new version of cairomm to coincide with the 1.6 release of cairo.