in reply to Msg.pm extended with "workproc". IO::Select docs

Test based on documentation:

use strict; use warnings; use IO::Select qw( ); use IO::Socket qw( ); my $lsn = IO::Socket::INET->new(Listen => 1, LocalPort => 8080); my $sel = IO::Select->new( $lsn ); my $no_error = my ($r_ready, $w_ready, $e_ready) = IO::Select->select($sel, undef, undef, 2.2); if ($no_error) { print("No error\n"); print("Num readers ready: ", 0+@$r_ready, "\n"); print("Num writers ready: ", 0+@$w_ready, "\n"); print("Num errors ready: ", 0+@$e_ready, "\n"); } else { print("Error ", 0+$!, ": $!\n"); }
Win>perl a.pl Error 0: linux$ perl a.pl Error 29: Illegal seek

Timeout returns as an error, but with a useless error message. There's no way to differentiate between errors and timeouts, and $! is only valid for errors.

What about select? It could possibly return undef on error and 0 on timeout.

Turns out it returns -1 on error.

use strict; use warnings; use IO::Socket qw( ); my $lsn = IO::Socket::INET->new(Listen => 1, LocalPort => 8080); my $r_in = my $w_in = my $e_in = ''; vec($r_in, fileno($lsn), 1) = 1; vec($r_in, 100, 1) = 1 if $ARGV[0]; my $nfound = select( my $r_ready = $r_in, my $w_ready = $w_in, my $e_ready = $e_in, 2.2, ); $nfound >= 0 or die("select: (" . (0+$^E) . ") $^E\n"); if ($nfound) { print("nfound = $nfound\n"); } else { print("Timeout\n"); }
Win>perl a.pl 0 Timeout Win>perl a.pl 1 select: (10038) Unknown error Using $^E instead of $! gives select: (10038) An operation was attempted on something that is not a socket linux$ perl a.pl 0 Timeout linux$ perl a.pl 1 select: (9) Bad file descriptor

So the documentation for select needs to mention it returns -1 on error and that a timeout is not an error.

And the following line needs to be changed in IO::Select's select:

- if(select($rb,$wb,$eb,$t) > 0) + if(select($rb,$wb,$eb,$t) >= 0)

(Well, you could come up with a more efficient implementation.)

With the fix to IO::Select, the usage would be:

use strict; use warnings; use IO::Select qw( ); use IO::Socket qw( ); my $lsn = IO::Socket::INET->new(Listen => 1, LocalPort => 8080); my $sel = IO::Select->new( $lsn ); my ($r_ready, $w_ready, $e_ready) = IO::Select->select($sel, undef, undef, 2.2) or die("Can't select: (" . (0+$!) . ") $!\n"); if (@$r_ready + @$w_ready + @$e_ready == 0) { print("Timeout\n"); } else { print("Num readers ready: ", 0+@$r_ready, "\n"); print("Num writers ready: ", 0+@$w_ready, "\n"); print("Num errors ready: ", 0+@$e_ready, "\n"); }
  • Comment on timeouts and errors with IO::Select:: and CORE:: select (was Re: Msg.pm extended with "workproc". IO::Select docs)
  • Select or Download Code

Replies are listed 'Best First'.
Re: timeouts and errors with IO::Select:: and CORE:: select (was Re: Msg.pm extended with "workproc". IO::Select docs)
by Wiggins (Hermit) on Oct 12, 2009 at 13:15 UTC
    Thanks... I obviously got my metaphors mixed. All is well and the quest continues...
    Clarification for my enlightenment. The fore part of the statement
    my $no_error = my ($r_ready, $w_ready, $e_ready) = IO::Select->select($sel, undef, undef, 2.2);
    sets $no_error true if any of the element in the list are defined. And in the case of the TIMEOUT, they will always all be undefined?

    It is always better to have seen your target for yourself, rather than depend upon someone else's description.

      IO::Select::select is documented to return an empty list (zero values) on error. It also returns this on timeout.

      And in the case of the TIMEOUT, they will always all be undefined?

      Assigning an empty list to a variable will undefine it, so yes.

      sets $no_error true if any of the element in the list are defined.

      Yes, but not directly. $no_error is set to the number of values returned by IO::Select::select. Since IO::Select::select returns either an empty list or three references, the vars are only undefined when $no_error is false, and they're always undefined when $no_error is false.