Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gdb debugging (with breakpoint): Gtk-WARNING **: Invalid text buffer iterator

How can I debug (and reach some breakpoint) with gdb my buggy program (using GTK3) showing:

(monimelt:161): Gtk-WARNING **: Invalid text buffer iterator: either the iterator
is uninitialized, or the characters/pixbufs/widgets in the buffer have been
modified since the iterator was created.
You must use marks, character numbers, or line numbers to preserve a position 
across buffer modifications.
You can apply tags and insert marks without invalidating your iterators,
but any mutation that affects 'indexable' buffer contents (contents that can 
be referred to by character offset)
will invalidate all outstanding iterators

FWIW, the faulty program is some GPLv3 free software that I am developing (the same I asked this question for, where I give more context and explanation). It is on github: commit fc8e0b247d8dac4 (to reproduce my bug, build it, run it as ./monimelt, type exactly p a y TAB in the window labelled monimelt command).

I have tried (all, in the same gdb session):

  • calling quite early in my main the g_log_set_default_handler function (as suggested here) with my own mom_g_log_handler log handler and put a gdb breakpoint there

  • putting a gdb breakpoint on g_warning (does not work, since that is probably a macro)

  • putting a gdb breakpoint on g_log_default_handler

  • also calling (in commit fb374425c69f2ddbd...)

    g_log_set_handler ("Gtk", G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL
                       | G_LOG_LEVEL_ERROR | G_LOG_LEVEL_WARNING
                       | G_LOG_FLAG_RECURSION, mom_g_log_handler, NULL);
    

    don't help...

But those breakpoints are not reached and the Gtk-WARNING **: Invalid text buffer iterator message is still appearing.

Perhaps GTK is creating some pthreads, or perhaps it is registering its own log handler...

how I found my bug....

I finally found my bug (corrected in commit 82bb111402fdd97...). It was two calls to gtk_text_iter_get_offset happening (incorrectly) after gtk_text_buffer_insert.

But I am not satisfied with the way I found my bug. I had to fetch gtk+-3.21.6.tar.xz and I patched its gtk/gtktextiter.c to code near line 180 the following:

extern void basile_gtk_text_iter_warning (void);
void basile_gtk_text_iter_warning (void)
{
  usleep (1000);
}

/* This function ensures that the segment-dependent information is
   truly computed lazily; often we don't need to do the full make_real
   work. This ensures the btree and line are valid, but doesn't
   update the segments. */
static GtkTextRealIter*
gtk_text_iter_make_surreal (const GtkTextIter *_iter)
{
  GtkTextRealIter *iter = (GtkTextRealIter*)_iter;

  if (iter->chars_changed_stamp !=
      _gtk_text_btree_get_chars_changed_stamp (iter->tree))
    {
      g_warning ("Invalid text buffer iterator: either the iterator "
                 "is uninitialized, or the characters/pixbufs/widgets "
                 "in the buffer have been modified since the iterator "
                 "was created.\nYou must use marks, character numbers, "
                 "or line numbers to preserve a position across buffer "
                 "modifications.\nYou can apply tags and insert marks "
                 "without invalidating your iterators,\n"
                 "but any mutation that affects 'indexable' buffer contents "
                 "(contents that can be referred to by character offset)\n"
                 "will invalidate all outstanding iterators");
      basile_gtk_text_iter_warning ();
      return NULL;
    }

The only change I made (w.r.t. pristine GTK3.21.26) is the definition and call to basile_gtk_text_iter_warning and I put a breakpoint in it with gdb.

Being able to do such dirty tricks is one of the reasons I am only using free software as much as possible, but having to make such tricks is really a shame, and there must be a better way.

So my question still stands, how could I have put such a breakpoint without recompiling GTK3? Or more generally how could I use GDB to catch such bugs (of course without recompiling GTK3).

BTW, using the simple --g-fatal-warnings option is not really a solution, since I am also getting

(monimelt:21949): Gtk-WARNING **: Failed to get the GNOME session proxy: 
The name org.gnome.SessionManager is not owned

which I consider being a spurious warning, because my running desktop is Mate, not Gnome. And my code is calling gtk_application_new & g_application_run and having a activate signal on my mom_gtkapp.


PS. On Linux/Debian/Sid/x86-64, GTK3 is 3.21.5, compiled with GCC6 and -g3 -Og flags...

like image 345
Basile Starynkevitch Avatar asked Sep 15 '16 10:09

Basile Starynkevitch


2 Answers

You can break on a g_warning (and any other log level message) by putting a breakpoint on g_logv.

I found this info here, fyi: http://wiki.inkscape.org/wiki/index.php/Debugging_Inkscape

like image 157
Stepan Avatar answered Sep 22 '22 13:09

Stepan


Use G_DEBUG=fatal-warnings gdb ./your_app to make gdb stop on warnings, too.

Reference: https://developer.gnome.org/glib/unstable/glib-Message-Logging.html#g-warning

like image 42
DarkTrick Avatar answered Sep 21 '22 13:09

DarkTrick