Fix IO::Socket::connect() in the light of $! changes
authorSteve Hay <steve.m.hay@googlemail.com>
Tue, 3 Sep 2013 21:57:46 +0000 (22:57 +0100)
committerSteve Hay <steve.m.hay@googlemail.com>
Mon, 16 Sep 2013 14:37:31 +0000 (15:37 +0100)
We now assign Exxx values rather than WSAExxx values to $! in the event of a
sockets error if there is an Exxx value corresponding to the WSAExxx error.
This is indeed the case for several Exxx values < 100, amongst them EINVAL (22),
which corresponds to WSAEINVAL (10022), which IO::Socket::connect() has a test
for.  Note that the test used a hard-coded value for WSAExxx since there were
(and still are) no constants in Perl for that.  Users will now be able to test
for EINVAL instead, but no existing code will be using that because it has
always had the value 22.

This non-backwards-compatible breakage seems unavoidable if we are to get things
in a sane state for the future because it is really a problem with how things
have long been, namely that $! was being set to winsock2.h values, but if there
was a corresponding errno.h value and it was < 100 then *that* was used for the
Errno/POSIX constant, so authors had no good way of testing for such $! values.
The new scheme corrects that by consistently using the same values for $! and
for Errno/POSIX [except in the case of third-party code setting its own $!/errno
values, which will be addressed in the next commit].

(Ironically, Exxx values >= 100 (the ones which caused all this trouble in the
first place!) don't have this problem as long as code uses the Exxx constants
rather than the hard-coded 100XX numbers.  For example, if code tests $! ==
ECONNABORTED, where $! and ECONNABORTED were both previously set to winsock2.h
values then the same test will still work, except that now $! and ECONNABORTED
are both set to errno.h values in VC10+ (or both left as winsock2.h values upto
VC9).  It does still break if any code is directly testing $! == 10053, but
that's not such a problem: that's really broken code, which should be using the
constant instead.)

dist/IO/lib/IO/Socket.pm

index aa3c9ad..9b0f34d 100644 (file)
@@ -24,7 +24,7 @@ require IO::Socket::UNIX if ($^O ne 'epoc' && $^O ne 'symbian');
 
 @ISA = qw(IO::Handle);
 
-$VERSION = "1.36";
+$VERSION = "1.36_01";
 
 @EXPORT_OK = qw(sockatmark);
 
@@ -135,11 +135,13 @@ sub connect {
                $@ = "connect: timeout";
            }
            elsif (!connect($sock,$addr) &&
-                not ($!{EISCONN} || ($! == 10022 && $^O eq 'MSWin32'))
+                not ($!{EISCONN} || ($^O eq 'MSWin32' &&
+                $! == ($] < 5.019004) ? 10022 : Errno::EINVAL))
             ) {
                # Some systems refuse to re-connect() to
                # an already open socket and set errno to EISCONN.
-               # Windows sets errno to WSAEINVAL (10022)
+               # Windows sets errno to WSAEINVAL (10022) (pre-5.19.4) or
+               # EINVAL (22) (5.19.4 onwards).
                $err = $!;
                $@ = "connect: $!";
            }