This works fine:
#!/usr/bin/perl -w
#
#pipe2 - use pipe and fork so child can send to parent
use IO::Handle;
pipe(READER, WRITER);
WRITER->autoflush(1);
if ($pid = fork) {
close WRITER;
chomp($line = <READER>);
print "Parent Pid $$ just read this: `$line'\n";
close READER;
waitpid($pid,0);
} else {
die "cannot fork: $!" unless defined $pid;
close READER;
print WRITER "Child Pid $$ is sending this\n";
close WRITER; # this will happen anyway
exit;
}
But when I try to make the reader not block with fcntl as this:
use IO::Handle;
use Fcntl;
pipe(READER, WRITER);
WRITER->autoflush(1);
if ($pid = fork) {
close WRITER;
fcntl(fileno(READER),F_GETFL,$flags)
or die "Couldn't get flags for READER : $!\n";
$flags |= O_NONBLOCK;
fcntl(fileno(READER), F_SETFL, $flags)
or die "Couldn't set flags for READER $!\n";
chomp($line = <READER>);
print "Parent Pid $$ just read this: `$line'\n";
close READER;
waitpid($pid,0);
} else {
die "cannot fork: $!" unless defined $pid;
close READER;
print WRITER "Child Pid $$ is sending this\n";
close WRITER; # this will happen anyway
exit;
}
I get:
fcntl() on unopened filehandle 3 at pip2.pl line 14.
Couldn't get flags for READER : Bad file descriptor
I need to "watch" the child and do something if it doesn't respond properly within a specific time. I need async communications with the child.
fcntl(fileno(READER),F_GETFL,$flags)
fcntl
gets a filehandle, not a file number. Use fcntl(READER,...
not fcntl(fileno(READER), ...
.
Apart from that it is recommended to not use global symbols for file handles. Better use local variables, i.e.
pipe(my $reader, my $writer);
$writer->autoflush();
...
Apart from not being in potential conflict to other global symbols and avoiding risks of uncaught typos, this will also close the respective file handles ones the variable gets out of scope.