http://qs1969.pair.com?node_id=427056

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

Okay, I know there are 3 obvious reasons IO::Select::can_read returns:

1) a filehandle has data to be read
2) a filehandle has been closed
3) timeout

The problem is, I'm running into cases where can_read returns, but none of the above is true. Unfortunately, it's a big, bloated bunch of libraries and scripts to make it run, and I haven't been able to condense it into a simple testcase that others can use to reproduce it. But I can show you the code:

# instead of simply reading on the socket filehandle, we'll # use IO::Select here to give us timeout capabilities. # add the socket to our IO::Select object. # my $sel = new IO::Select ($sock); # $sock is a IO::Socket obj # now wait until our IO::Select obj tells us that one of its # sockets (and we only added one) is ready to be read (or # times out). # if (my @socks = $sel->can_read($timeout)) { $sock = shift(@socks); # ...read socket data, or print warning if the # socket was closed remotely... } else { croak sprintf("Timed out, socket connection status: %d\n", defined($sock->connected())); }

In most cases this works fine, with a $timeout value of say 300. Occasionally, however, I'll instantly fall through to the else clause, clearly not having waited for $timeout seconds. If I set $timeout to undef it works. I am certain that the message I'm attempting to read is being sent in all cases, why is it that if I have a $timeout value I get this odd behavior? Are there known reasons that can_read would return undef before the $timeout seconds have elapsed?

Thanks.

20050203 Edit by castaway: Changed title from 'What makes can_read return?'

Replies are listed 'Best First'.
Re: What makes IO::Select::can_read return?
by sleepingsquirrel (Chaplain) on Feb 01, 2005 at 22:30 UTC
    One possibility, (from the man page for the select system call)...
    Any signal will cause select to return immediately. So if your program uses signals, you can't rely on select to keep waiting for the full time specified. If you want to be sure of waiting for a particular amount of time, you must check for EINTR and repeat the select with a newly calculated timeout based on the current time. See the example below.

    I don't really know how Perl ends up wrapping the underlying system call. Might be something to check into.


    -- All code is 100% tested and functional unless otherwise noted.
      Run the program below and do a kill -USR1, to see it in action.
      #!/usr/bin/perl -w use IO::Select; my $sel = new IO::Select (\*STDIN); $SIG{USR1} = sub { print "signal\n"}; if (my @socks = $sel->can_read(50)) { warn "Got Here\n"; } else { warn "Else: $!\n"; }


      -- All code is 100% tested and functional unless otherwise noted.
      You guys rule. Yeah, I was getting a SIGCHLD when I thought all my child processes were already cleaned up. Just had to stick a print in the sig handler to catch it. Thanks monks!
Re: What makes IO::Select::can_read return?
by Joost (Canon) on Feb 01, 2005 at 22:38 UTC
    If I read the docs:
    can_read ( [ TIMEOUT ] ) Return an array of handles that are ready for reading. "TIM +EOUT" is the maximum amount of time to wait before returning an empt +y list, in seconds, possibly fractional. If "TIMEOUT" is not given and + any han- dles are registered then the call will block.

    It never says it's always going to wait for the TIMEOUT, it just says it's not going to wait longer than the timeout.

    AFAIK this might be a bug in perl, a bug in your OS, or it might be a completely reasonable effect of the way select() is implemented... According to my select(2) manpage (on Linux) errno should be set when select(2) returns -1. Try printing $! in your else routine.

    Also note that you should not use buffered IO when using select (so use sysread() and syswrite() instead of read() if you don't already).