Lost input in quickfill cells due to race

Jim Paris jim at jtan.com
Mon May 23 17:03:54 EDT 2011


Hi,

If I type quickly into a quickfill cell, some of my input is lost.
It's especially pronounced when X-forwarding over a slower link, but
I've seen it on fast links and even locally.  I've tracked it down to
a race condition in src/register/register-gnome/gnucash-sheet.c:

    if (start_sel != end_sel)
    {
        select_info *info;

        info = g_malloc(sizeof(*info));
        info->editable = editable;
        info->start_sel = start_sel;
        info->end_sel = end_sel;
        g_timeout_add(/*ASAP*/ 1,
                               (GSourceFunc)gnucash_sheet_select_data_cb,
                               info);
    }

This sets up a short-lived timer that will change the selection.
However, other keypresses can show up in the GTK event queue before
the timeout expires.

The attached patch adds debugging that shows the race.  I'll type
"asdf" into a cell that quickfills "asdf".  If I type very slowly,
the debugging output shows:

gnucash_sheet_insert_cb: insert_text='a', position=0
  scheduling timeout, start_sel=1, end_sel=-1
gnucash_sheet_select_data_cb: start_sel=1, end_sel=-1
gnucash_sheet_insert_cb: insert_text='s', position=1
  scheduling timeout, start_sel=2, end_sel=-1
gnucash_sheet_select_data_cb: start_sel=2, end_sel=-1
gnucash_sheet_insert_cb: insert_text='d', position=2
  scheduling timeout, start_sel=3, end_sel=-1
gnucash_sheet_select_data_cb: start_sel=3, end_sel=-1
gnucash_sheet_insert_cb: insert_text='f', position=3
  scheduling timeout, start_sel=4, end_sel=-1
gnucash_sheet_select_data_cb: start_sel=4, end_sel=-1

and the cell contains "asdf" as expected. If I instead type it quickly,

gnucash_sheet_insert_cb: insert_text='a', position=0
  scheduling timeout, start_sel=1, end_sel=-1
gnucash_sheet_insert_cb: insert_text='s', position=1
gnucash_sheet_insert_cb: insert_text='d', position=2
gnucash_sheet_select_data_cb: start_sel=1, end_sel=-1
gnucash_sheet_insert_cb: insert_text='f', position=1

Note how the 's' and 'd' arrived before the selection callback.  The
wrong text was selected, and the final 'f' overwrote the entire
selection.  The cell contains just "af" after this.

Setting the selection can't be done asynchronously like this.
I'll see if I can come up with a clean fix...

-jim


commit b94910babbe66350ad455dcd5a8074298c873dfc
Author: Jim Paris <jim at jtan.com>
Date:   Mon May 23 16:53:59 2011 -0400

    Add debugging for keyboard input issues

diff --git a/src/register/register-gnome/gnucash-sheet.c b/src/register/register-gnome/gnucash-sheet.c
index 3d0d6b9..1137a55 100644
--- a/src/register/register-gnome/gnucash-sheet.c
+++ b/src/register/register-gnome/gnucash-sheet.c
@@ -854,6 +854,8 @@ typedef struct
 static gboolean
 gnucash_sheet_select_data_cb (select_info *info)
 {
+    printf("gnucash_sheet_select_data_cb: start_sel=%d, end_sel=%d\n",
+	   info->start_sel, info->end_sel);
     gtk_editable_select_region (info->editable,
                                 info->start_sel, info->end_sel);
     g_free(info);
@@ -889,6 +891,9 @@ gnucash_sheet_insert_cb (GtkWidget *widget,
     const char *c;
     gunichar uc;
 
+    printf("gnucash_sheet_insert_cb: insert_text='%s', position=%d\n",
+	   insert_text, *position);
+
     if (sheet->input_cancelled)
     {
         g_signal_stop_emission_by_name (G_OBJECT (sheet->entry),
@@ -1006,6 +1011,8 @@ gnucash_sheet_insert_cb (GtkWidget *widget,
         info->editable = editable;
         info->start_sel = start_sel;
         info->end_sel = end_sel;
+	printf("  scheduling timeout, start_sel=%d, end_sel=%d\n",
+	       info->start_sel, info->end_sel);
         g_timeout_add(/*ASAP*/ 1,
                                (GSourceFunc)gnucash_sheet_select_data_cb,
                                info);



More information about the gnucash-devel mailing list