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

David Campbell david at pastornet.net.au
Fri Nov 9 05:41:31 UTC 2007


Hi,

Back in August Oliver proposed a fix to an xsane bug that I found 
[details below], and the fix does work.

Is there likely to be an xsane release sometime that includes this fix?  
I'm just wondering when the fix will work its way into various distros, 
eg Fedora?

-- Dave

David Campbell wrote:
> Hi Oliver,
>
> Yes, that does correct the issue.  Thanks!
>
>
>
> Oliver Rauch wrote:
>   
>> Hello David,
>>
>> I think this would be a suitable solution:
>>
>>
>> replace
>>  if (val != new_val)
>> by
>>  if (abs(val - new_val) > 1)
>>
>> please could you verify if this solves the problem even with -O2
>> compiler option!
>>
>> Best regards
>> Oliver
>>
>> Am Mittwoch, den 08.08.2007, 19:27 +1000 schrieb David Campbell:
>>   
>>     
>>> 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
>>>>
>>>>
>>>>
>>>>   
>>>>       
>>>>         
>>> -- 
>>> sane-devel mailing list: sane-devel at lists.alioth.debian.org
>>> http://lists.alioth.debian.org/mailman/listinfo/sane-devel
>>> Unsubscribe: Send mail with subject "unsubscribe your_password"
>>>              to sane-devel-request at lists.alioth.debian.org
>>>     
>>>       
>>
>>   
>>     
>
>   



More information about the sane-devel mailing list