[sane-devel] xsane infinite loop lockup - seems to boil down to compiler optimisation difference

David Campbell david at pastornet.net.au
Tue Aug 7 04:15:52 UTC 2007


Hi,

I've been experiencing an infinite loop with xsane when it is starting 
up when using the hp5590 driver.  I'm seeing it both in the head version 
of the fedora 7 distribution, and when I build xsane from source.

If you set XSANE_DEBUG in the environment to 1000, then you can see it 
doing this over and over:

[xsane] xsane_control_option(option = 4, action = 1)
[xsane] xsane_update_param
[xsane] xsane_control_option(option = 4, action = 0)
[xsane] xsane_get_option_descriptor(4)
[xsane] xsane_back_gtk_value_update
[xsane] xsane_get_option_descriptor(4)
[xsane] xsane_back_gtk_set_option

It seems that to be all happening when at line 2479 of xsane-back-gtk.c 
g_signal_emit_by_name() is called, and xsane_back_gtk_value_update() 
gets called repeated.

(gdb) where
#0  xsane_back_gtk_value_update (adj_data=0x82ce160, elem=0x82b9660)
    at xsane-back-gtk.c:1879
#1  0x00957199 in g_cclosure_marshal_VOID__VOID ()
   from /lib/libgobject-2.0.so.0
#2  0x00949da2 in g_closure_invoke () from /lib/libgobject-2.0.so.0
#3  0x0095a4d3 in ?? () from /lib/libgobject-2.0.so.0
#4  0x0095b9f7 in g_signal_emit_valist () from /lib/libgobject-2.0.so.0
#5  0x0095dd8e in g_signal_emit_by_name () from /lib/libgobject-2.0.so.0
#6  0x0805284c in xsane_back_gtk_update_scan_window () at 
xsane-back-gtk.c:2479

It is clear that xsane_back_gtk_value_update is being called over and 
over again, but xsane_back_gtk_update_scan_window is not being called 
over and over.

I believe I've found the cause of this problem, and it seems to be a 
difference in behaviour when gcc optimises the code, and I can see the 
difference occur on gcc 4.12-12 on fedora 7 and also on a really old 
linux running gcc 2.96.

If you compile xsane without optimisation, it works fine!

In xsane_back_gtk_value_update, in the handling of "case 
SANE_TYPE_FIXED", it assigns a value to the variable "val", but the 
value of "val" is always differing by one value from the value of the 
"new_val" variable, and so it enters the "if (new_val != val) statement, 
which in turn triggers a call to xsane_back_gtk_value_update again.

I stripped it down to a little snippet of code, and you can see that 
this program below gives a different result when compiled with -O2 than 
it does when compiled without -O2.  Also, if you uncomment the print 
statements below, you get different behaviour.

Note the difference here:
[dcampbel at Vigor12 src]$ gcc -o bug bug.c; ./bug; gcc -O2 -o bug bug.c; ./bug
stage 1: d = 59.539708
39019943
stage 1: d = 59.539708
39019942

/* bug.c - to be run on linux since it hard-codes a binary 
representation of floating point number */
#include <stdio.h>
#include <stdlib.h>

int main()
{
 int val, new_val;
 double d;
 unsigned char *c = (unsigned char *)&d;
 if(sizeof(d) != 8) {
   fprintf(stderr, "Wrong architecture\n");
   exit(1);
 }
 c[0] = 102;
 c[1] = 102;
 c[2] = 102;
 c[3] = 38;
 c[4] = 21;
 c[5] = 197;
 c[6] = 77;
 c[7] = 64;

 printf("stage 1: d = %lf\n", d);
 d *= 10.0;
 /*printf("stage 2: d = %lf\n", d);*/
 d = d * (1 << 16);
 /*printf("stage 3: d = %lf\n", d);*/
 val = (int)d;
 printf("%d\n", val);
 exit(0);
}

-- Dave



More information about the sane-devel mailing list