8201474: (so) Socket adaptor connect(InetAddress, timeout) succeeds when connection fails
authoralanb
Sat, 14 Apr 2018 08:41:42 +0100
changeset 49702 09c01737ad27
parent 49701 8c85a1855e10
child 49703 d2bea17edd96
8201474: (so) Socket adaptor connect(InetAddress, timeout) succeeds when connection fails Reviewed-by: bpb
src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java
src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java
src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java
src/java.base/unix/native/libnio/ch/Net.c
test/jdk/java/nio/channels/SocketChannel/AdaptSocket.java
--- a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java	Fri Apr 13 11:14:49 2018 -0700
+++ b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java	Sat Apr 14 08:41:42 2018 +0100
@@ -1280,8 +1280,8 @@
             boolean polled = false;
             try {
                 beginRead(blocking, false);
-                int n = Net.poll(fd, Net.POLLIN, timeout);
-                polled = (n > 0);
+                int events = Net.poll(fd, Net.POLLIN, timeout);
+                polled = (events != 0);
             } finally {
                 endRead(blocking, polled);
             }
--- a/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Fri Apr 13 11:14:49 2018 -0700
+++ b/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Sat Apr 14 08:41:42 2018 +0100
@@ -431,8 +431,8 @@
             boolean polled = false;
             try {
                 begin(true);
-                int n = Net.poll(fd, Net.POLLIN, timeout);
-                polled = (n > 0);
+                int events = Net.poll(fd, Net.POLLIN, timeout);
+                polled = (events != 0);
             } finally {
                 end(true, polled);
             }
--- a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java	Fri Apr 13 11:14:49 2018 -0700
+++ b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java	Sat Apr 14 08:41:42 2018 +0100
@@ -951,8 +951,8 @@
             boolean polled = false;
             try {
                 beginRead(blocking);
-                int n = Net.poll(fd, Net.POLLIN, timeout);
-                polled = (n > 0);
+                int events = Net.poll(fd, Net.POLLIN, timeout);
+                polled = (events != 0);
             } finally {
                 endRead(blocking, polled);
             }
@@ -977,10 +977,13 @@
                 boolean polled = false;
                 try {
                     beginFinishConnect(blocking);
-                    int n = Net.poll(fd, Net.POLLCONN, timeout);
-                    polled = (n > 0);
+                    int events = Net.poll(fd, Net.POLLCONN, timeout);
+                    polled = (events != 0);
                 } finally {
-                    endFinishConnect(blocking, polled);
+                    // invoke endFinishConnect with completed = false so that
+                    // the state is not changed to ST_CONNECTED. The socket
+                    // adaptor will use finishConnect to finish.
+                    endFinishConnect(blocking, /*completed*/false);
                 }
                 return polled;
             } finally {
--- a/src/java.base/unix/native/libnio/ch/Net.c	Fri Apr 13 11:14:49 2018 -0700
+++ b/src/java.base/unix/native/libnio/ch/Net.c	Sat Apr 14 08:41:42 2018 +0100
@@ -700,7 +700,8 @@
     if (rv >= 0) {
         return pfd.revents;
     } else if (errno == EINTR) {
-        return IOS_INTERRUPTED;
+        // interrupted, no events to return
+        return 0;
     } else {
         handleSocketError(env, errno);
         return IOS_THROWN;
--- a/test/jdk/java/nio/channels/SocketChannel/AdaptSocket.java	Fri Apr 13 11:14:49 2018 -0700
+++ b/test/jdk/java/nio/channels/SocketChannel/AdaptSocket.java	Sat Apr 14 08:41:42 2018 +0100
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 8156002
+ * @bug 8156002 8201474
  * @summary Unit test for socket-channel adaptors
  * @library .. /test/lib
  * @build jdk.test.lib.Utils TestServers
@@ -37,18 +37,16 @@
 
 public class AdaptSocket {
 
-    static java.io.PrintStream out = System.out;
+    static final java.io.PrintStream out = System.out;
 
-    static void test(TestServers.DayTimeServer dayTimeServer,
+    static void test(TestServers.AbstractServer server,
                      int timeout,
                      boolean shouldTimeout)
         throws Exception
     {
         out.println();
 
-        InetSocketAddress isa
-            = new InetSocketAddress(dayTimeServer.getAddress(),
-                                    dayTimeServer.getPort());
+        InetSocketAddress isa = new InetSocketAddress(server.getAddress(), server.getPort());
         SocketChannel sc = SocketChannel.open();
         Socket so = sc.socket();
         out.println("opened: " + so);
@@ -151,6 +149,30 @@
         sc.close();
     }
 
+    static void testConnect(TestServers.AbstractServer server,
+                            int timeout,
+                            boolean shouldFail)
+        throws Exception
+    {
+        SocketAddress sa = new InetSocketAddress(server.getAddress(), server.getPort());
+        try (SocketChannel sc = SocketChannel.open()) {
+            Socket s = sc.socket();
+            try {
+                if (timeout > 0) {
+                    s.connect(sa, timeout);
+                } else {
+                    s.connect(sa);
+                }
+                if (shouldFail)
+                    throw new Exception("Connection should not be established");
+            } catch (SocketException se) {
+                if (!shouldFail)
+                    throw se;
+                out.println("connect failed as expected: " + se);
+            }
+        }
+    }
+
     public static void main(String[] args) throws Exception {
 
         try (TestServers.DayTimeServer dayTimeServer
@@ -177,5 +199,9 @@
                 = TestServers.NoResponseServer.startNewServer()) {
             testRead(noResponseServer, 10, true);
         }
+
+        TestServers.RefusingServer refuser = TestServers.RefusingServer.newRefusingServer();
+        testConnect(refuser, 0, true);
+        testConnect(refuser, 2000, true);
     }
 }