dagolden / Capture-Tiny

(Perl) Capture STDOUT and STDERR from Perl, XS or external programs
http://search.cpan.org/dist/Capture-Tiny/
39 stars 19 forks source link

tee hangs when ran across forks #53

Closed mark-5 closed 7 years ago

mark-5 commented 7 years ago

If you fork multiple children, and tee in them, the tmpfile names can get reused in the children, which causes tee to wait on files cleaned up by other processes. I believe what's happening is that the same random number seed is being used in the child procs, which makes tmpnam return identical file names.

Below is an example which triggers this case.

#!/usr/bin/env perl
use strict;
use warnings;
use Capture::Tiny qw(tee);
use POSIX qw();

my $random = rand(); # something to set the rng seed

my @pids;
my $children = 2;
for (1 .. $children) {
    if (my $pid = fork) {
        push @pids, $pid;
    } else {
        # uncommenting will stop it from hanging
        # srand();
        tee { 42 };
        POSIX::_exit(0);
    }
}
waitpid($_, 0) for @pids;

I was able to work around the issue by calling srand in the children, but I believe this could be safely fixed inside Capture::Tiny if the tmp files included pids in the name. This would guarantee uniqueness across children.

xdg commented 7 years ago

Great catch. File::Temp normally has some defense against that but not for tmpnam.

xdg commented 7 years ago

Released Capture-Tiny-0.47-TRIAL.tar.gz to CPAN.