This excellent question How to read to and write from a pipe in Perl? provides an excellent answer.
It doesn't work on ActiveState Perl.
The BUGS section of perlfork http://docs.activestate.com/activeperl/5.14/lib/pods/perlfork.html says
In certain cases, the OS-level handles created by the pipe(), socket(), and accept() operators are apparently not duplicated accurately in pseudo-processes. This only happens in some situations, but where it does happen, it may result in deadlocks between the read and write ends of pipe handles, or inability to send or receive data across socket handles.
It is not clear what 'not duplicated accurately' means or if it even applies in this case.
Here is the test program
#! /usr/bin/env perl
use strict;
use warnings;
my $isActiveStatePerl = 1 ; # defined(&Win32::BuildNumber);
sub pipeFromFork
{
return open($_[0], "-|") if (!$isActiveStatePerl);
pipe $_[0], my $child or die "cannot create pipe";
printf STDERR "$$: pipe create parent %d child %d\n", fileno($_[0]), fileno($child);
my $pid = fork();
die "fork failed: $!" unless defined $pid;
if ($pid) { # parent
printf STDERR "$$: fork parent close child %d\n", fileno($child);
close $child;
} else { # child
open(STDOUT, ">&=", $child) or die "cannot clone child to STDOUT";
printf STDERR "$$: fork child close parent %d stdout %d\n", fileno($_[0]), fileno(STDOUT);
close $_[0];
}
return $pid;
}
my @transform = qw( tr [A-Za-z] [N-ZA-Mn-za-m] ); # rot13
my @inception = (
"V xabj, Qnq. Lbh jrer qvfnccbvagrq gung V pbhyqa'g or lbh.",
"V jnf qvfnccbvagrq gung lbh gevrq.",
);
sub snow_fortress { print STDERR "$$: 1 start\n"; print map "$_\n", @inception }
sub hotel
{
printf STDERR "$$: 2 start %d\n", fileno(STDIN);
# my $pid = open STDIN, "-|";
my $fh;
my $pid = pipeFromFork($fh);
print STDERR "$$: hotel: pid $pid\n";
defined($pid) or die "$0: fork: $!";
if (0 == $pid) {
snow_fortress;
print STDERR "$$: 1 exit\n";
exit(0);
}
open(STDIN, "<&", $fh) or die "cannot clone to STDIN";
printf STDERR "$$: 2 exec %d\n", fileno(STDIN);
# print while <STDIN>;
exec @transform or die "$0: exec: $!";
}
# my $pid = open my $fh, "-|";
my $pid = pipeFromFork(my $fh);
defined($pid) or die "$0: fork: $!";
print STDERR "$$: outer: pid $pid\n";
if (0 == $pid) {
hotel;
print STDERR "$$: 2 exit\n";
exit(0);
}
print STDERR "$$: 3 start " . fileno($fh) . "x\n";
print while <$fh>;
print STDERR "$$: 3 end\n";
close $fh or warn "$0: close: $!";