in reply to First SELECT of FIFO still blocked ?
In addition to the <> operator used blocking and relying on perlio as an earlier reply noted, your open() call will block until the FIFO is opened. To avoid blocking on that, you'd probably need some kind of SIGALRM handler and an alarm() timeout, like this:
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"; }
Remember that with unbuffered reads (you'd need sysread() for that) you don't get neat breaks on newlines, so you'd want to test for "\n" characters in your result. I've given some very simple example code below that only reads a single character, but this is highly inefficient because it causes a system read(2) call for every character read.
Smarter is to do chunked reads of up to a reasonable block size (choices between 1-8 KiB of data are common,) then scan that for a newline, printing out each segment and moving the buffer forward that much. However, I've opted to ignore those kind of performance details to keep the example below simple. You'd presumably want to do so if you cared at all about performance under any kind of real load.
Here's a trivial server/client example for a unbuffered read on a pipe. Note that the client (the writer) is buffered out of convenience, and that the server "idles" when the select(2) call has nothing to do. Typically in an unbuffered read loop you're busy doing other tasks.
These examples assume you have created the pipe node on your filesystem in the same directory you run these scripts from. Also note what happens to the server if you start it and do not send data into the pipe. See what debug lines you get, and determine why. Play around with the alarm code from above to avoid blocking here.
File: read-unbuf.pl (the server that reads a fifo)
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 newline +s: 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 "."; }
File: write-pipe.pl (the client that writes lines into a fifo from STDIN)
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: $!";
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: First SELECT of FIFO still blocked ?
by Aquarius (Initiate) on Dec 17, 2015 at 10:29 UTC |