in reply to forked kid can't read from IO::Select->can_read

You're suffering from multiple diseases.

First of all, try to give us something that should work cut-and-paste if there was no error. This helps us concentrate on the problem you have instead of working out a new example from the scratch, and helps you have more answers.

Then, IO::Select says:

can_read ( [ TIMEOUT ] ) Return an array of handles that are ready for reading. "TIMEOUT" is the maximum amount of time to wait before returning an empty list, in seconds, possibly frac- tional. If "TIMEOUT" is not given and any handles are registered then the call will block.
So it doesn't return the lines which wait to be read, but the handles that have data and that you can read from.

Last, but not least, you're maybe suffering from buffering. You don't provide much information about SOCKET/SOC, but note that if it buffers you could wait a long time before something is output. Unless it's really some socket, in which case you'd not.

Here's a working example, you'll be able to adapt it to your case easily. Note that the child sleeps 5 seconds, then checks for data in handles and reads from them.

#!/usr/bin/perl use warnings; use strict; use IO::Select; my $pid = open(PIP, "|-"); if ($pid < 0) { die "open(): $!"; } elsif ($pid > 0) { print scalar localtime time, " - Parent: sending something to chil +d\n"; print PIP "Hi, son!\n"; print scalar localtime time, " - Parent: waiting for child to fini +sh\n"; close PIP; print scalar localtime time, " - Parent: exiting\n"; } else { my $selector = IO::Select->new(\*STDIN); print scalar localtime time, " - Child: just born!\n"; sleep(60); my @handles = $selector->can_read(0); if (@handles) { print scalar localtime time, " - Child: there are " . scalar(@ +handles) . " handles ready for reading\n"; # It can only be STDIN... my $line = <STDIN>; chomp($line); print scalar localtime time, " - Child: parent says: [$line]\n +"; } print scalar localtime time, " - Child: exiting\n"; exit(0); } __END__ Sun May 22 15:43:48 2005 - Parent: sending something to child Sun May 22 15:43:48 2005 - Child: just born! Sun May 22 15:43:48 2005 - Parent: waiting for child to finish Sun May 22 15:44:48 2005 - Child: there are 1 handles ready for readin +g Sun May 22 15:44:48 2005 - Child: exiting Sun May 22 15:44:48 2005 - Parent: exiting
As a final note, always check the return status of open, it can fail!

Flavio (perl -e 'print(scalar(reverse("\nti.xittelop\@oivalf")))')

Don't fool yourself.

Replies are listed 'Best First'.
Re^2: forked kid can't read from IO::Select->can_read
by Anonymous Monk on May 22, 2005 at 14:19 UTC
    Frodo,

    ahh! (&& uups, sorry)

    I understand my mistake, I thought that can_reads returns the buffered lines, but it returns only the 'readable' handles - ok.
    But now I'm thrown back to my old problem:

    while (<HANDLE>) {..}
    waits until a EOL is sent and then executs the the block {..}.
    So what if I don't want to wait for that EOL, but what if I have to send what I have got exactly at the full minute?

    So frankly spoken how can I (the kid of course) read from STDIN all what is there and return immediately if nothing is there anymore?

    Thanks in advance,
    Carl

      Using the <> way of reading from a socket means you're using buffered reading, which is a bad idea when using select, or in this case IO::Select. Instead I would recommend using sysread() to do the actual reading. Now, the nice thing about sysread() is that every time it does a read, it returns the amount of bytes actually read in. So if you were to do for example:
      my $scalar; my $bytes = sysread(FILEHANDLE, $scalar, 1024);
      and $bytes turns out to be less than 1024, then it's a pretty safe assumption that there's nothing left. If on the other hand you get the full 1024 you can just go ahead and do another read, and so on, and so on.


      Remember rule one...
      Using regular buffered reads, you don't really have much control over it. Most likely, it will block even if you sent exactly one line, because at the time of the actual (hidden) sysread, it doesn't know that there's a full line available -- it just reads a fixed number of bytes.

      So you have two options. One is to do a select and a sysread for every individual byte. This is probably easier but very inefficient.

      Another is to change STDIN to be nonblocking, and try to sysread large chunks at a time. Keep trying until sysread returns undef, and then check $!{EWOULDBLOCK}. Completely untested:

      sub read_available { my ($fh) = @_; my $data = ''; while (1) { my $buf; my $nread = sysread($fh, $buf, 4096); if (defined $nread) { if ($nread == 0) { # End of file, so we have everything we'll ever get return ($data, 1); } else { $data .= $buf; } } else { if ($!{EWOULDBLOCK}) { return ($data, 0); } else { return; # Error } } } } . . . # Set STDIN nonblocking IO::Handle->new_from_fd(fileno(STDIN), "r")->blocking(0); . . . # If select says that STDIN is readable... my ($data, $eof) = read_available(*STDIN) or die "Error reading stdin: $!";

      I really should test this once, but hopefully it gives the right idea. Seems like a correct version of this routine ought to be in a FAQ somewhere. Or maybe it is; I didn't check.

        Hi again,

        thank you for your support, in return this code which works for me quite well.

        It migth be a good idea to put that in FAQ, but carfully look for key words as I sometimes do not know for which words to look for!

        Some remarks to this code
        Using the STDIN within the function of the kid I didn't get anything from STDIN. Only this way I was able to get the lines from 'dad'.

        Unblocking the read of course forces you to do a sleep or wait (like my function to wait for full minute) otherwise the kid will heat up the pc ;-). It is a bit self adapting to keep the buffer reasonable small..

        Not to have so many loops in loops in loops, I first push all readables in @LINES and the treat them.

        Who ever wants/will write this FAQ-topic may use/change it.

        Thanks for all
        Carl

        use IO::Handle; my ($readPIPE,$writePIPE, $pid); pipe $readPIPE, $writePIPE; $writePIPE->autoflush(1); $pid = fork; if ( !$pid ) { # child close($writePIPE); nonBlockingRead( $readPIPE ); exit; } else { # parent close($readPIPE); my (n,$s) = (0,0); while (1) { $s = (int(rand( 50 ))); sleep (int(rand( 50 ))); print $writePIPE "Dad: line ",++$n," after $s s\n"; } } sub nonBlockingRead { use IO::Select; my $PIPE = ( shift ); my $SEL = IO::Select->new( $PIPE ); my @LINES = qw ( ini deafault array size ); IO::Handle->new_from_fd(fileno( $PIPE ),"r")->blocking(0); while ( $SEL->exists( $PIPE ) ) { ($sleep,$send) = doWait( $sleep, scalar @LINES ); @LINES = (); foreach my $h ( $SEL->can_read(0) ) { push @LINES, ( <$h> ); } foreach my $l ( @LINES ) { &doSomething( $l ); } } } sub doWait { my $sec = (shift); my $NoL = (shift); #: every whole min $sec = ($NoL>20)?($sec/2):(($NoL< 5)?($sec+1):$sec); my $m = 60 - (time%60); if ( ( $m - $sec/2 ) < $sec ) { sleep ($m-0.2); return ($sec, 1); # ok full Min } else { sleep ($sec); return ($sec, 0); # default } }
      I agree with the previous answers, you'd jump to a lower-layer sysread to do this.

      I usually use select immediately before each sysread, trying to read big chunks of data at one time. But I do this because, in the mean case, I manage more than one handle at one time, so I use select to make an intelligent wait upon multiple sources. If you only have to read from one handle, you'd probably go for a non-blocking read (if you have to do something else while data is arriving, of course).

      And yes, I admit that I cheated a bit in my answer, because I added a "\n" in the data sent by the father, and a chomp in the kid :)

      Flavio (perl -e 'print(scalar(reverse("\nti.xittelop\@oivalf")))')

      Don't fool yourself.