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