[sane-devel] xsane infinite loop lockup - seems to boil down to compiler optimisation difference
David Campbell
david at pastornet.net.au
Wed Aug 8 09:27:52 UTC 2007
Hi,
OK - thanks for your comment!
Here's what I am seeing from the debug entry you request:
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
[xsane] val = 39019942, new_val = 39019943
etc forever....
A bit of output from gdb, and note that it is taking the SANE_TYPE_FIXED
branch of the switch statement in the code, so the value of val comes
from the SANE_FIX macro.
(gdb) p adj_data->value
$1 = 59.539707946777341
(gdb) p d
$2 = 595.39707946777344
(gdb) p val
$3 = 39019942
(gdb) p new_val
$5 = 39019943
You can simulate exactly what is going on here with this bit of tiny C
source code below, which hard-codes the binary representation of 59.5397
from above, and you can see that the resulting behaviour depends on
whether you compile with optimization or not, and you get 390199423 or
39019942 respectively. Also, uncommenting the printf comments below
changes the compiler's decision about whether to use registers or not to
store the value of d and can change the resulting output from the
arithmetic.
/* 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
Oliver Rauch wrote:
> Am Dienstag, den 07.08.2007, 22:28 +1000 schrieb David Campbell:
>
>
>> This means that the current comparison "if (new_val != val)" in the
>> xsane_back_gtk_value_update() function in xsane-back-gtk.c is invalid,
>> because if there is the slightest difference in the floating point value
>> (and there can be if the compiler has decided to implement the code
>> optimally using processor registers), it will attempt to set the value
>> again, and I'm seeing an infinite looping happening there because it
>> never gets to the point where the values are the same!
>>
>
>
> if (new_val != val) ...
>
> in general (and also in this case) is allowed.
> Please note that val and new_val are not floating point numbers in this code, they have the type SANE_Word (= int).
> So we have an integer comparison here.
>
> Please could you add some debug output to xsame-back-gtk.c after these lines:
>
> xsane_back_gtk_set_option(opt_num, &val, SANE_ACTION_SET_VALUE);
> xsane_control_option(xsane.dev, opt_num, SANE_ACTION_GET_VALUE, &new_val, 0);
> DBG(0, "val = %d, new_val = %d\n", val, new_val);
>
> and send a little trace of it when the infinit loop occurs.
>
>
> Best regards
> Oliver
>
>
>
>
More information about the sane-devel
mailing list