|Anonymous | Login | Signup for a new account||2014-11-28 10:36 CET|
|Main | My View | View Issues | Change Log | Roadmap|
|View Issue Details|
|ID||Project||Category||View Status||Date Submitted||Last Update|
|0006032||OCaml||OCaml standard library||public||2013-06-05 14:14||2013-06-06 13:45|
|Priority||normal||Severity||minor||Reproducibility||have not tried|
|Target Version||Fixed in Version|
|Summary||0006032: Random.self_init problem under Windows|
|Description||Under Windows, the random seed is computed from the process id and the current time. As a result, the following will (with high probability) display twice the same number:|
let () =
Printf.printf "%i\n%!" (Random.int 10000);
Printf.printf "%i\n%!" (Random.int 10000)
The code for caml_win32_random_seed (in win32.c) suggests an improvement (using RtlGenRandom). A simpler fix for the case above could be obtained simply by using a static counter (so that the same process calling self_init twice in a row will get different seeds). I want to check that nobody is against this fix.
|Tags||No tags attached.|
The static counter isn't going to add any entropy, even though it would make the problem less apparent. I'd prefer to look for other sources of randomness: if not the Win32 crypto API, at least something like the TSC register of x86 processors.
I'd be tempted to use QueryPerformanceCounter, which looks reasonably portable under Win32:
int caml_win32_random_seed (intnat data)
data = t.dwLowDateTime;
data = t.dwHighDateTime;
data = GetCurrentProcessId();
data = pc.LowPart;
data = pc.HighPart;
What about using:
maybe with a fallback (for the unlikely case where the symbol is not found in the dll or the dll cannot be loaded) to your solution.
Well, using RtlGenRandom is what the comment in win32.c suggests. However, the MSDN doc is scary: "[this function] may be altered or unavailable in subsequent versions [of Windows]". CryptGenRandom is certainly more durable, but risks pulling in all of the Win32 Crypto API.
Another suspicious point: truly cryptography-quality PRNGs block until enough entropy has been gathered. (That's the difference between /dev/random and /dev/urandom under Linux.) We don't want to risk blocking while initializing OCaml's Random library module. The MSDN docs don't say whether RtlGenRandom and CryptGenRandom can block, and how to avoid blocking.
Could you be so nice as to try the QueryPerformanceCounter-based solution I suggested? (I no longer have a working Win32 development environment.) Thanks in advance.
> Could you be so nice as to try the QueryPerformanceCounter-based solution I suggested? (I no longer have a working Win32 development environment.) Thanks in advance.
Yes, it seems to work (tried with the 32-bit msvc port).
edited on: 2013-06-06 13:45
Commit 13750 to trunk.
|Commit 13751 adds a non-regression test (which might fail with very low probability).|
|2013-06-05 14:14||frisch||New Issue|
|2013-06-05 14:28||xleroy||Note Added: 0009410|
|2013-06-05 14:28||xleroy||Status||new => acknowledged|
|2013-06-05 15:08||xleroy||Note Added: 0009411|
|2013-06-05 15:45||frisch||Note Added: 0009412|
|2013-06-05 19:58||xleroy||Note Added: 0009414|
|2013-06-06 09:23||frisch||Note Added: 0009418|
|2013-06-06 13:42||frisch||Note Added: 0009421|
|2013-06-06 13:42||frisch||Assigned To||=> frisch|
|2013-06-06 13:42||frisch||Status||acknowledged => assigned|
|2013-06-06 13:45||frisch||Note Added: 0009422|
|2013-06-06 13:45||frisch||Status||assigned => resolved|
|2013-06-06 13:45||frisch||Resolution||open => fixed|
|2013-06-06 13:45||frisch||Note Edited: 0009421||View Revisions|
|Copyright © 2000 - 2011 MantisBT Group|