8012244: java/net/Socket/asyncClose/Race.java fails intermittently on Windows
authorchegar
Tue, 16 Apr 2013 13:26:30 +0100
changeset 16866 e659009ee08d
parent 16865 e443e809a4ab
child 16867 76499721c6c1
child 16903 63829f318ebf
child 16919 5370bde84770
8012244: java/net/Socket/asyncClose/Race.java fails intermittently on Windows Reviewed-by: alanb, dsamersoff
jdk/src/windows/classes/java/net/DualStackPlainSocketImpl.java
jdk/src/windows/native/java/net/SocketInputStream.c
jdk/test/java/net/Socket/asyncClose/Race.java
--- a/jdk/src/windows/classes/java/net/DualStackPlainSocketImpl.java	Tue Apr 16 12:51:22 2013 +0100
+++ b/jdk/src/windows/classes/java/net/DualStackPlainSocketImpl.java	Tue Apr 16 13:26:30 2013 +0100
@@ -152,8 +152,9 @@
         if (!fd.valid())
             return;
 
-        close0(fdAccess.get(fd));
+        final int nativefd = fdAccess.get(fd);
         fdAccess.set(fd, -1);
+        close0(nativefd);
     }
 
     void socketShutdown(int howto) throws IOException {
--- a/jdk/src/windows/native/java/net/SocketInputStream.c	Tue Apr 16 12:51:22 2013 +0100
+++ b/jdk/src/windows/native/java/net/SocketInputStream.c	Tue Apr 16 13:26:30 2013 +0100
@@ -134,32 +134,35 @@
         (*env)->SetByteArrayRegion(env, data, off, nread, (jbyte *)bufP);
     } else {
         if (nread < 0) {
-            /*
-             * Recv failed.
-             */
-            switch (WSAGetLastError()) {
-                case WSAEINTR:
-                    JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
-                        "socket closed");
-                    break;
+            // Check if the socket has been closed since we last checked.
+            // This could be a reason for recv failing.
+            if ((*env)->GetIntField(env, fdObj, IO_fd_fdID) == -1) {
+                NET_ThrowSocketException(env, "Socket closed");
+            } else {
+                switch (WSAGetLastError()) {
+                    case WSAEINTR:
+                        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+                            "socket closed");
+                        break;
 
-                case WSAECONNRESET:
-                case WSAESHUTDOWN:
-                    /*
-                     * Connection has been reset - Windows sometimes reports
-                     * the reset as a shutdown error.
-                     */
-                    JNU_ThrowByName(env, "sun/net/ConnectionResetException",
-                        "");
-                    break;
+                    case WSAECONNRESET:
+                    case WSAESHUTDOWN:
+                        /*
+                         * Connection has been reset - Windows sometimes reports
+                         * the reset as a shutdown error.
+                         */
+                        JNU_ThrowByName(env, "sun/net/ConnectionResetException",
+                            "");
+                        break;
 
-                case WSAETIMEDOUT :
-                    JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
-                                   "Read timed out");
-                    break;
+                    case WSAETIMEDOUT :
+                        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
+                                       "Read timed out");
+                        break;
 
-                default:
-                    NET_ThrowCurrent(env, "recv failed");
+                    default:
+                        NET_ThrowCurrent(env, "recv failed");
+                }
             }
         }
     }
--- a/jdk/test/java/net/Socket/asyncClose/Race.java	Tue Apr 16 12:51:22 2013 +0100
+++ b/jdk/test/java/net/Socket/asyncClose/Race.java	Tue Apr 16 13:26:30 2013 +0100
@@ -23,8 +23,8 @@
 
 /*
  * @test
- * @bug 8006395
- * @summary Race in async socket close on Linux
+ * @bug 8006395 8012244
+ * @summary Tests racing code that reads and closes a Socket
  */
 
 import java.io.InputStream;
@@ -58,7 +58,7 @@
                                     Thread.sleep(50);
                             } catch (Exception x) {
                                 if (!(x instanceof SocketException
-                                      && x.getMessage().equals("Socket closed")))
+                                      && x.getMessage().equalsIgnoreCase("socket closed")))
                                     x.printStackTrace();
                                 // ok, expect Socket closed
                             }