Description
Description
As part of my exploration into the guts of how Perl handles random numbers I've come across some interesting things. When rand()
is called without calling srand()
first, a "random" seed is chosen to kick off the drand48 PRNG.
On Linux (or any system with /dev/urandom
) the seed is chosen by taking four bytes from urandom and generating a U32 from it. For 90% of use cases this is probably find for a general seed. This is good, well thought out, and the correct way to seed a PRNG.
On non-Linux systems, or when /dev/urandom
fails to read, Perl fails back to very simple hash of: unixtime, Perl PID, Pointer address, and a hash of a pointer address. On it's face this should be a semi-decent random seed. It would be pretty difficult to guess or repeat a given seed.
However after doing some testing I'm finding that repeated calls to seed()
return very similar values. Usually the values only vary between 2 to 4 bits.
Steps to Reproduce
Call the seed()
function repeatedly
3106881140, 3106881131, 3106881119, 3106881110
662064185, 662064176, 662064164, 662064155
2315860893, 2315860881, 2315860869, 2315860857
I used the following code:
PerlIO_printf(Perl_debug_log, "SEED: %u/%u/%u/%u\n", seed(), seed(), seed(), seed());
at the end of the Perl_drand48_init_r()
and then called rand()
from the CLI and saw the very similar values.
Expected behavior
Whatever seed()
function we employ, that has the sole purpose of seeding a PRNG, should return better, more spaced out, more randomish values. This is very easily solved by simply employing a better hash of the u
value at the end of Perl_seed(pTHX)
. To be clear, this only affects systems where we do not read from /dev/urandom
. Windows I'm looking at you.
This should be a pretty simple fix, and I'd like to take a run at it. Before I go too much farther I need to figure out the status of #22962 so I can move forward appropriately.