فهرست منبع

Fix for trwsync.pp sporadic failure that appeared in trunk.
The problem was in the source of random related functions,
which are used in this test by several thread in parallel,
while this code is known and advertised as non-thread safe.

The access by multiple threads led to multiple increments of the
mt_index static variable, which was then never reset to zero and
led to all successive calls to random function to return zero.

This fix simply insures that the mt_state array is never
accessed past its end, and that mt_index is reset correctly even
if multiple increments do happen.

It does not make the random function thread-safe.

* Use local variable l_index to avoid accessing mt_state array past last element.
* Change mt_index=MTWIST_N+1 into l_index>=MTWIST_N+1
to insure that mt_init will be called again if index is past end.

git-svn-id: trunk@34320 -

pierre 9 سال پیش
والد
کامیت
b9e336dcbe
1فایلهای تغییر یافته به همراه11 افزوده شده و 4 حذف شده
  1. 11 4
      rtl/inc/system.inc

+ 11 - 4
rtl/inc/system.inc

@@ -606,9 +606,13 @@ end;
 
 
 
 
 function mtwist_u32rand: cardinal;
 function mtwist_u32rand: cardinal;
+var
+  l_index :cardinal;
 begin
 begin
+  l_index:=mt_index;
+  inc(mt_index);
   if (RandSeed<>OldRandSeed) or
   if (RandSeed<>OldRandSeed) or
-     (mt_index=MTWIST_N+1) then
+     (l_index>=MTWIST_N+1) then
     begin
     begin
       mtwist_init(RandSeed);
       mtwist_init(RandSeed);
       { Detect resets of randseed
       { Detect resets of randseed
@@ -619,11 +623,14 @@ begin
       }
       }
       RandSeed:=not(RandSeed);
       RandSeed:=not(RandSeed);
       OldRandSeed:=RandSeed;
       OldRandSeed:=RandSeed;
+      l_index:=MTWIST_N;
     end;
     end;
   if mt_index=MTWIST_N then
   if mt_index=MTWIST_N then
-    mtwist_update_state;
-  result:=mt_state[mt_index];
-  inc(mt_index);
+    begin
+      mtwist_update_state;
+      l_index:=0;
+    end;
+  result:=mt_state[l_index];
   result:=result xor (result shr 11);
   result:=result xor (result shr 11);
   result:=result xor ((result shl 7) and cardinal($9D2C5680));
   result:=result xor ((result shl 7) and cardinal($9D2C5680));
   result:=result xor ((result shl 15) and cardinal($EFC60000));
   result:=result xor ((result shl 15) and cardinal($EFC60000));