[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