in reply to Non blocking read on a filehandle

I've found this following routine useful. Basically it allows me to just get nonblocking full lines of input from a filehandle (using the select/vec solution - and heavily based on tadman's code above).
# An non-blocking filehandle read that returns an array of lines read # Returns: ($eof,@lines) my %nonblockGetLines_last; sub nonblockGetLines { my ($fh,$timeout) = @_; $timeout = 0 unless defined $timeout; my $rfd = ''; $nonblockGetLines_last{$fh} = '' unless defined $nonblockGetLines_last{$fh}; vec($rfd,fileno($fh),1) = 1; return unless select($rfd, undef, undef, $timeout)>=0; # I'm not sure the following is necessary? return unless vec($rfd,fileno($fh),1); my $buf = ''; my $n = sysread($fh,$buf,1024*1024); # If we're done, make sure to send the last unfinished line return (1,$nonblockGetLines_last{$fh}) unless $n; # Prepend the last unfinished line $buf = $nonblockGetLines_last{$fh}.$buf; # And save any newly unfinished lines $nonblockGetLines_last{$fh} = (substr($buf,-1) !~ /[\r\n]/ && $buf =~ s/([^\r\n]*)$//) ? $1 : ''; $buf ? (0,split(/\n/,$buf)) : (0); }
I've tested it with a pipe I opened using an IO::File, YMMV. Example usage:
$fh = new IO::File; open($fh,"$cmd 2>&1 |"); do { ($eof,@lines) = nonblockGetLines($fh); foreach my $line ( @lines ) { print "Pipe saw: [$line]\n"; } } until $eof; close $fh;
I don't know enough about vec() to know why tadman called it twice, don't know if this is a race condition or if it's unneeded, and at this point don't care enough to figure it out - I've got other code to write! :) Enjoy!

Replies are listed 'Best First'.
Re^2: Non blocking read on a filehandle
by Anonymous Monk on Nov 20, 2008 at 16:41 UTC
    > # I'm not sure the following is necessary?
    > return unless vec($rfd,fileno($fh),1);

    select() allows you to check for many file descriptors at once by adding each fd into the $rfd vector. The $rfd gets modified by select() to let you know which file descriptors are available.

    The second line of code here verifies that the file descriptor you asked about is one that's ready.