In the code below, I am trying to perform a simple file operation. Suppose foo.txt is completely empty. I would expect the first can_read () to block, but that is not the case. You also cannot use can_read calls in sysreadline () or wait. Instead, the first can_read immediately returns a handle to foo.txt, and the first can_read in sysreadline does the same. Sysread then returns nothing, because there is nothing to read, which leads to lively waiting inside sysreadline. How can it be? I know that the choice may end earlier due to a signal or a closed file descriptor, but I do not see any possibility for this here. In fact, when the text appears (with a new line) in the foo.txt file, it prints. I donβt understand why the code does not block indefinitely, like the first can_read, when there is nothing to read.In addition to wasting CPU, this makes it impossible to use multiple files at the same time, because you will always get stuck in the first wait. I feel like I should overlook something simple ...
This is perl 5.8.8
use strict;
use IO::Select;
use IO::Handle;
use Symbol qw(qualify_to_ref);
open my $inf, "<", "foo.txt" or die "hey! Can't open foo.txt!\n";
my $sel = IO::Select->new();
$sel->add($inf);
while(my @ready = $sel->can_read()){
foreach my $handle (@ready){
my $line = sysreadline($handle);
print $line;
}
}
sub sysreadline {
my($handle, $timeout) = @_;
$handle = qualify_to_ref($handle, caller( ));
my $infinitely_patient = (@_ == 1 || $timeout new( );
$selector->add($handle);
my $line = "";
SLEEP:
until (at_eol($line)) {
unless ($infinitely_patient) {
return $line if time( ) > ($start_time + $timeout);
}
next SLEEP unless $selector->can_read(1.0);
INPUT_READY:
while ($selector->can_read(0.0)) {
my $was_blocking = $handle->blocking(0);
CHAR: while (sysread($handle, my $nextbyte, 1)) {
$line .= $nextbyte;
last CHAR if $nextbyte eq "\n";
}
$handle->blocking($was_blocking);
next SLEEP unless at_eol($line);
last INPUT_READY;
}
}
return $line;
}
sub at_eol($) { $_[0] =~ /\n\z/ }
source
share