There needs to be a blocking() sub which uses ioctl() instead of
allowing IO:Handle's blocking sub to do the work. And some of the if
conditions in the connect() function need to be changed to reflect the
fact that Windows uses EWOULDBLOCK instead of EINPROGRESS and WSAEINVAL
(10022) instead of EISCONN.
Note that the following are based on the IO::Socket which came with
ActiveState Perl 5.8.0 build 806. Also note that the blocking() sub
doesn't handle the case of just checking the blocking state of a socket
using $somesock->blocking().
Here is a blocking sub which would work (assuming that the fixed version
of ioctl from change 19534 is being used):
sub blocking {
my $sock = shift;
return $sock->SUPER::blocking(@_) unless $^O =~ /Win32/;
#Windows handles blocking differently
my $nonblocking = $_[0] ? "0" : "1";
#0x8004667e is FIONBIO
return ioctl($sock, 0x8004667e, \$nonblocking);
}
and here is the modified connect (sorry this isn't a diff)
sub connect {
@_ == 2 or croak 'usage: $sock->connect(NAME)';
my $sock = shift;
my $addr = shift;
my $timeout = ${*$sock}{'io_socket_timeout'};
my $err;
my $blocking;
$blocking = $sock->blocking(0) if $timeout;
if (!connect($sock, $addr)) {
if (defined $timeout && ($!{EINPROGRESS} || ($^O =~ /Win32/ &&
$!{EWOULDBLOCK}))) {
require IO::Select;
my $sel = new IO::Select $sock;
if (!$sel->can_write($timeout)) {
$err = $! || (exists &Errno::ETIMEDOUT ? &Errno::ETIMEDOUT : 1);
$@ = "connect: timeout";
}
elsif (!connect($sock,$addr) && not ($!{EISCONN} || ($^O =~
/Win32/ && $! == 10022))) {
# Some systems refuse to re-connect() to
# an already open socket and set errno to EISCONN.
# Windows sets errno to WSAEINVAL (10022)
$err = $!;
$@ = "connect: $!";
}
}
elsif ($blocking || !($!{EINPROGRESS} || ($^O =~ /Win32/ &&
$!{EWOULDBLOCK}))) {
$err = $!;
$@ = "connect: $!";
}
}
$sock->blocking(1) if $blocking;
$! = $err if $err;
$err ? undef : $sock;
}
According to my network programming book, both EWOULDBLOCK and
EINPROGRESS are valid errno values for a nonblocking connect.
However, the fact that neither of these two constants are in Errno.pm
probably should be considered a bug. (At least, they aren't there
in Activestate Perl 5.6.1, with local patch 631)
--
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "$@[$a%6
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}
Benjamin Goldberg wrote:
> Robert Moser II wrote:
>
>>There needs to be a blocking() sub which uses ioctl() instead of
>>allowing IO:Handle's blocking sub to do the work. And some of the if
>>conditions in the connect() function need to be changed to reflect the
>>fact that Windows uses EWOULDBLOCK instead of EINPROGRESS and WSAEINVAL
>>(10022) instead of EISCONN.
>
> According to my network programming book, both EWOULDBLOCK and
> EINPROGRESS are valid errno values for a nonblocking connect.
With that being the case, the "$^O =~ /Win32/ &&" portions could be
dropped to make it a bit cleaner. It just seems like Windows is the
only one where EWOULDBLOCK is used. The bit with WSAEINVAL is a bit
harder to simplify, since no other platform has that particular error.
> However, the fact that neither of these two constants are in Errno.pm
> probably should be considered a bug. (At least, they aren't there
> in Activestate Perl 5.6.1, with local patch 631)
And they still aren't there in ActivePerl 5.6.1.635. However, they are
present in ActivePerl 5.8.0.806, which is what I based my changes on. I
also seem to recall something about the $!{ERROR} construction not being
valid in 5.6.1. There doesn't seem to be anything majorly different
between the 5.8.0.806 and 5.6.1.635 versions of Errno.pm other than the
addition of about 37 error numbers, mostly networking related, so maybe
if a 5.6.1.636 build is released, those constants could be in there.
WSAEINVAL is just Win32 bolt-on for EINVAL from sockets DLL.
--
Nick Ing-Simmons
http://www.ni-s.u-net.com/
That is mostly true. Note that WSAEINVAL != EINVAL though. WSAEINVAL ==
10022 and EINVAL == 22.
I see no pattern there it is not as though 10000 is a round number ;-)
That is the trouble with "bolt ons" - the bolt-heads are there to scrape
your shins on...
You must remember that back in '90s networks were optional on PCs
so Win32 did not need them to be tightly integrated ;-)