Daniel Miron
Daniel Miron

Reputation: 460

Perl File::Temp, file name not random

I have a strange problem using File::Temp:

I am running my perl script under mod_perl in Apache on Linux, Apache is running with worker mpm.

my ($fh_error, $error)
    = tempfile("error_XXXXXXXXXXXXXXXX",DIR => "/home/tmp", UNLINK => 1);
my ($fh_src, $src) 
    = tempfile("src_XXXXXXXXXXXXXXXX",DIR => "/home/tmp", UNLINK => 1, SUFFIX => ".html");          
my ($fh_dst, $dst) 
    = tempfile("dst_XXXXXXXXXXXXXXXX",DIR => "/home/tmp", UNLINK => 1, SUFFIX => ".html");

Most of the time, everything seems to be ok, but every now or then I get some bad file names. Instead of getting a true random file name, I get the same letter for all the template length.

for example

error_AAAAAAAAAAAAAAAA
src_AAAAAAAAAAAAAAAA
dst_AAAAAAAAAAAAAAAA

All 3 files get the same name. Except of this just being strange (and you never want your code being strange), I'm afraid this may result in reading/writing to the same file for different from different requests.

Upvotes: 1

Views: 688

Answers (1)

Joe Z
Joe Z

Reputation: 17936

I looked at the source for File::Temp. It replaces the Xs in the template with this concise bit of perl:

    $path =~ s/X(?=X*$end)/$CHARS[ int( rand( @CHARS ) ) ]/ge;

That uses perl's built-in rand, which is just a traditional seed-based random number generator. That rand function is not cryptographically secure. Its seed is also 'global state', which can lead to problems when forking, as described here:

http://blogs.perl.org/users/brian_phillips/2010/06/when-rand-isnt-random.html

The jist of it is: If you fork two perl interpreters, and the original interpreter was already seeded by a single call to rand, both inherit the same seed after the fork, so both will generate the same random number sequence from that point. Ooops. So, you may want to call srand one in your module before calling tempfile or anything else that calls rand.

That said, it appears File::Temp takes great pains to detect and avoid collisions, but it will give up at some point. The following warning is buried in the File::Temp docs:

    If you are forking many processes in parallel that are all creating 
    temporary files, you may need to reset the random number seed using 
    srand(EXPR) in each child else all the children will attempt to walk 
    through the same set of random file names and may well cause themselves 
    to give up if they exceed the number of retry attempts.

Upvotes: 3

Related Questions