From 5cb00695e6cfd81163cab5f6b4a72e81b84a2c20 Mon Sep 17 00:00:00 2001
From: Eric Wong <e@80x24.org>
Date: Thu, 16 Apr 2015 02:25:05 +0000
Subject: [PATCH] connect_nonblock(..., exception: false) does not raise
 EISCONN

This is to reduce exceptions for code which issues a (IMHO,
unnecessary) second connect() syscall.
---
 ext/socket/socket.c          | 6 ++++++
 test/socket/test_nonblock.rb | 1 +
 2 files changed, 7 insertions(+)

diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index a514b9a..bb23703 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -509,6 +509,12 @@ sock_connect_nonblock(int argc, VALUE *argv, VALUE sock)
             }
             rb_readwrite_sys_fail(RB_IO_WAIT_WRITABLE, "connect(2) would block");
 	}
+	if (errno == EISCONN) {
+            if (!NIL_P(opts) &&
+                    Qfalse == rb_hash_lookup2(opts, sym_exception, Qundef)) {
+                return INT2FIX(0);
+            }
+	}
 	rsock_sys_fail_raddrinfo_or_sockaddr("connect(2)", addr, rai);
     }
 
diff --git a/test/socket/test_nonblock.rb b/test/socket/test_nonblock.rb
index 6912046..2973bdb 100644
--- a/test/socket/test_nonblock.rb
+++ b/test/socket/test_nonblock.rb
@@ -69,6 +69,7 @@ class TestSocketNonblock < Test::Unit::TestCase
       assert_equal :wait_writable, rv
     end
     assert_equal([ [], [c], [] ], IO.select(nil, [c], nil, 60))
+    assert_equal 0, c.connect_nonblock(servaddr, exception: false)
     s, sockaddr = serv.accept
     assert_equal(Socket.unpack_sockaddr_in(c.getsockname),
                  Socket.unpack_sockaddr_in(sockaddr))
-- 
EW

