my $pipe;
eval {
local $SIG{ALRM} = sub { die "alarm\n" };
alarm(5);
open( $pipe, "<", $pipe_path )
or die "pipe open failed: $!";
alarm(0);
};
if ($@) {
die unless ($@ eq "alarm\n"); # non-alarm failure.
die "timeout on pipe open";
}
####
use strict;
use warnings;
require IO::Select; # OO interface to select(2) & friends.
require IO::Handle; # treat handles as objects.
require POSIX; # supplies access to errno E* values
sub debug{ printf STDERR "%s\n", shift // ''; }
my $pipe_path = "pipe"; # you must mkfifo this file first!
debug("opening pipe");
open( my $pipe, "<", $pipe_path )
or die "pipe open failed: $!";
debug("pipe opened");
$pipe->blocking(0); # set non-blocking on the descriptor
my $s = IO::Select->new();
$s->add($pipe);
# Holds unbuffered chars read. We only want full lines:
my $buf = "";
# Inefficient polling loop. Nonblocking because we're "busy".
POLL:
while (1) {
# Nothing to do unless the FD reports ready.
# When there's no data, the 'continue' block is run.
next POLL unless ( my @ready = $s->can_read(.25) );
# This is really slow. Smarter would be to read in chunks,
# then search for a newline. If we have none, append to buffer.
# We take the slow approach for this example & read just 1 char.
my $bytes = $pipe->sysread( $buf, 1, length($buf) );
# You MUST test for errors using sysread. See docs, and read(2).
# In this case, we also must verify we don't get EAGAIN.
# In rare cases, select(2) indicates a possible read when there's not.
if (not defined $bytes) {
next POLL if ($! == POSIX->EAGAIN);
# Error: report $! (errno) and exit
debug("An error occurred on read: $!");
exit(1);
}
# $bytes == 0 means EOF. Nothing more to read.
if ($bytes == 0) {
print "Reached EOF. All done reading from pipe.\n";
close($pipe); # no point in checking for errors here.
exit(0);
}
# Otherwise, check the character just read. Print/reset on newlines:
if ( substr($buf, -1) eq "\n" ) {
print "Pipe line read: $buf";
$buf = "";
}
}
continue {
# Your idle work when there's nothing to do happens here.
# This silly example just prints a period each poll interval.
print STDERR ".";
}
####
use strict;
use warnings;
require IO::Handle;
my $pipe_path = "pipe";
open( my $pipe, ">", $pipe_path )
or die "pipe open failed: $!";
$pipe->autoflush(1);
while( my $line = <> ) {
chomp $line;
print $pipe $line . "\n";
}
close($pipe)
or die "Closing pipe failed: $!";