Use the exception set in select (connect()) to early return when remote end is busy...
authorKarthik Rajagopalan <rajagopa@pauline.schrodinger.com>
Thu, 14 Jul 2011 17:36:41 +0000 (13:36 -0400)
committerSteve Hay <steve.m.hay@googlemail.com>
Mon, 15 Aug 2011 20:17:20 +0000 (21:17 +0100)
For non blocking socket, it a timeout has been specified, IO::Socket internally use select(..) to
detect the result of socket connection. In situation, where remote end is busy or in non-existing port, we spend
entire timeout mentioned in select(..) call. We cannot completely differentiate if error is WSAECONNREFUSED(10061) or
WSAETIMEDOUT(10060) in this situation. If we use the exception set in select(..) call, we can do early return and also
a make a clear differentiation in error condition. This is same like what Linux handle in this situation.

dist/IO/lib/IO/Socket.pm

index 31fa18f..06e4e6c 100644 (file)
@@ -118,10 +118,21 @@ sub connect {
            my $sel = new IO::Select $sock;
 
            undef $!;
-           if (!$sel->can_write($timeout)) {
-               $err = $! || (exists &Errno::ETIMEDOUT ? &Errno::ETIMEDOUT : 1);
-               $@ = "connect: timeout";
-           }
+            my($r,$w,$e) = IO::Select::select(undef,$sel,$sel,$timeout);
+            if(@$e[0]) {
+                # Windows return from select after the timeout in case of
+                # WSAECONNREFUSED(10061) if exception set is not used.
+                # This behavior is different from Linux.
+                # Using the exception
+                # set we now emulate the behavior in Linux 
+                #    - Karthik Rajagopalan
+                $err = $sock->getsockopt(SOL_SOCKET,SO_ERROR);
+                $@ = "connect: $err";
+            }
+            elsif(!@$w[0]) {
+                $err = $! || (exists &Errno::ETIMEDOUT ? &Errno::ETIMEDOUT : 1);
+                $@ = "connect: timeout";
+            }
            elsif (!connect($sock,$addr) &&
                 not ($!{EISCONN} || ($! == 10022 && $^O eq 'MSWin32'))
             ) {