I'm trying to dispel the magic fork variant of open:
# magic-fork.pl
if (open my $fh, '-|') { # fork self, make new fd for reading, attach child STDOUT to it
STDOUT->say('parent getpid: ', $$);
STDOUT->say('parent STDOUT->fileno: ', STDOUT->fileno);
STDOUT->say('parent $fh->fileno: ', $fh->fileno);
while (my $line = $fh->getline) {
STDOUT->print('parent readline from child: ', $line);
}
} else {
STDOUT->say('child getpid: ', $$);
STDOUT->say('child STDOUT->fileno: ', STDOUT->fileno);
}
It runs and finishes.
# plain-fork.pl
pipe my $r, my $w;
if (fork) {
STDOUT->say('parent getpid: ', $$);
STDOUT->say('parent STDOUT->fileno: ', STDOUT->fileno);
STDOUT->say('parent $r->fileno: ', $r->fileno);
STDOUT->say('parent $w->fileno: ', $w->fileno);
while (my $line = $r->getline) {
STDOUT->print('parent readline from child: ', $line);
}
} else {
$w->say('child getpid: ', $$);
$w->say('child $r->fileno: ', $r->fileno);
$w->say('child $w->fileno: ', $w->fileno);
$w->say('child STDOUT->fileno: ', STDOUT->fileno);
}
This program unexpectedly hangs in the loop.
I tried to no avail:
What's the problem?
You pipe
before fork
ing (Like usual for this sort of IPC), so both processes have open copies of both the read and write file descriptors, so the read loop in the parent will just block waiting for more input which never comes from the still-open write end.
The child process needs to close $r;
, the parent process needs to close $w;
at the start of their respective blocks (Or after you print out the file descriptors for those handles).