Reputation: 460
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
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