in reply to File::Temp randomness when forking

The error occurs because you are calling tempdir before your loop. This makes File::Temp call srand internally, and all subsequent forks inherit the seeded random value.You can 'fix' this behaviour by explicitly calling srand($$) before your call to File::Temp->new() in the loop. You're probably right that it would be a good idea for the documentation to point out this particular quirk (or the module could work around it by comparing $$ between rand calls calling srand explicitly), I suggest you file a bug report at rt.cpan.org.

As an aside, you would probably have gotten a quicker response or even have found out the reason for yourself if the code you posted had been reduced to the bits necessary to demonstrate this bug. This would have sufficed (with the fix commented out):

use strict; use warnings; use Parallel::ForkManager; use File::Temp qw(tempdir tempfile); my $pm=new Parallel::ForkManager(15); my $tempdir = tempdir(); for my $i (1..15) { $pm->start and next; # srand($$); my $fh = File::Temp->new(TEMPLATE => "sappyXXXXXXXX", UNLINK => 0) or die "Could not make tem +pfile: $!"; close $fh or die "Could not close tempfile: $!"; $pm->finish(); } $pm->wait_all_children;

Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. -- Brian W. Kernighan

Replies are listed 'Best First'.
Re^2: File::Temp randomness when forking
by ryantate (Friar) on Nov 29, 2005 at 17:47 UTC
    The error occurs because you are calling tempdir before your loop. This makes File::Temp call srand internally, and all subsequent forks inherit the seeded random value.

    Thanks for this! I did not know this is how things work, didn't bother looking through the source for more than a few minutes.

    FWIW, I call tempdir first because I want all the forks to dump their files into the same dir so I can collect their output easily in the parent when they finish. (I would think this would be a common pattern, but maybe not.)

    This is why I included slightly more source than you personally would prefer -- I wanted to show a bit of why I am doing this the way I am doing it. It is reduced considerably from the actual code (down to 26 lines not counting __DATA__ vs. 13 lines for yours). On further consideration, I would probably cut it down as you suggest, and deal with any "why did you do this" questions as they come up (instead of preempting them).

    In any case, I doubt I would have stumbled on anything involving srand no matter how much I cut down my code, as it was never in my code! I only know about it because you pointed it out to me, so thanks.

    RT

      That's not necessarily what I meant. If you'd have cut down your code to the essentials you would have removed the tempdir call before the loop and suddenly it would not have failed. You'd then at least have this extra bit of information which you could have checked up on yourself in the File::Temp code or added to the post. And it would have been easier for someone to look at the problem and figure out what the problem was without the irrelevant bits of information. As I said, just an aside for future reference, sorry if it maybe came across a little harsh.


      Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. -- Brian W. Kernighan
        If you'd have cut down your code to the essentials you would have removed the tempdir call before the loop and suddenly it would not have failed.

        I see your broader point. I updated the node (before your reply) with the following sentence, I should have used an UPDATE tag but was hoping I was fast enough:

        "On further consideration, I would probably cut it down as you suggest, and deal with any 'why did you do this questions as they come up (instead of preempting them).

        That'll teach me to try and outrun other monks ;->

        UPDATE: In reality, I might not have rid myself of tempdir, the cut-down version you posted had it in there after all! But I do see your point.