http://www.perlmonks.org?node_id=837267

vsespb has asked for the wisdom of the Perl Monks concerning the following question:

Hi. I worked with a perl blocking sockets and found a weird thing.

Looks like IO::Select works bad when you read from sockets with <$fh> in case someone on the other end wrote to the socket _two_ or more lines. I.e. <$fh> will return one line. Second line will be read too by perl process but kept in perlio layer buffers. So IO::Select will return no sockets too read.

In practice this can produce hardly-to catch errors on application. I.e application can work _fine_ for a long time until it receive two lines at once cause of a big delay when handling previous lines.

I think this is lack in perl documentation. There is no word about this. Nothing about possible _read_ buffering problem. And lots of perl code all over the internet with io::select and <$fh>.

What do you think ?

Thanks.

Code (proof-of-concept):

#!/usr/bin/perl -w use strict; use IO::Select; use IO::Pipe; my $fromchild = new IO::Pipe; my $tochild = new IO::Pipe; my $pid; my $parent_pid = $$; if($pid = fork()) { # Parent $fromchild->reader(); $fromchild->autoflush(1); $fromchild->blocking(1); binmode $fromchild; $tochild->writer(); $tochild->autoflush(1); $tochild->blocking(1); binmode $tochild; my $read_set = new IO::Select(); # create handle set for reading $read_set->add($fromchild); while(1) { print "before select\n"; my ($rh_set, undef, $ex_set) = IO::Select->select($read_set, undef +, $read_set, 30); print "after select\n"; for my $rh (@$rh_set) { my $s = <$rh>; print "command: $s"; } } } elsif (defined ($pid)) { # Child $fromchild->writer(); $fromchild->autoflush(1); $fromchild->blocking(1); binmode $fromchild; $tochild->reader(); $tochild->autoflush(1); $tochild->blocking(1); binmode $tochild; print $fromchild "abc\n"; #sleep(1); ### IF you uncomment this line it will work print $fromchild "def\n"; sleep(86400); die; } __END__ =Output=: $ ./poc1.pl before select after select command: abc before select (process hangs here)