Merge
authorvinnie
Tue, 16 Apr 2013 05:32:39 -0700
changeset 16919 5370bde84770
parent 16918 a51c2ab502ff (current diff)
parent 16866 e659009ee08d (diff)
child 16920 d062d91d9dec
Merge
--- a/jdk/src/windows/classes/java/net/DualStackPlainSocketImpl.java	Tue Apr 16 05:11:50 2013 -0700
+++ b/jdk/src/windows/classes/java/net/DualStackPlainSocketImpl.java	Tue Apr 16 05:32:39 2013 -0700
@@ -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 05:11:50 2013 -0700
+++ b/jdk/src/windows/native/java/net/SocketInputStream.c	Tue Apr 16 05:32:39 2013 -0700
@@ -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 05:11:50 2013 -0700
+++ b/jdk/test/java/net/Socket/asyncClose/Race.java	Tue Apr 16 05:32:39 2013 -0700
@@ -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
                             }
--- a/jdk/test/java/util/concurrent/CompletableFuture/Basic.java	Tue Apr 16 05:11:50 2013 -0700
+++ b/jdk/test/java/util/concurrent/CompletableFuture/Basic.java	Tue Apr 16 05:32:39 2013 -0700
@@ -504,7 +504,7 @@
             cf1 = supplyAsync(() -> { throw new RuntimeException(); });
             cf2 = supplyAsync(() -> 2);
             cf3 = cf1.applyToEither(cf2, (x) -> { check(x == 2); return x; });
-            try { check(cf3.join() == 1); } catch (CompletionException x) { pass(); }
+            try { check(cf3.join() == 2); } catch (CompletionException x) { pass(); }
             check(cf3.isDone());
             check(cf1.isDone() || cf2.isDone());
 
@@ -520,6 +520,27 @@
             cf3 = cf1.applyToEitherAsync(cf2, (x) -> { fail(); return x; });
             checkCompletedExceptionally(cf3);
             check(cf1.isDone() || cf2.isDone());
+
+            final Phaser cf3Done = new Phaser(2);
+            cf1 = supplyAsync(() -> { cf3Done.arriveAndAwaitAdvance(); return 1; });
+            cf2 = supplyAsync(() -> 2);
+            cf3 = cf1.applyToEither(cf2, (x) -> { check(x == 2); return x; });
+            checkCompletedNormally(cf3, 2);
+            checkCompletedNormally(cf2, 2);
+            check(!cf1.isDone());
+            cf3Done.arrive();
+            checkCompletedNormally(cf1, 1);
+            checkCompletedNormally(cf3, 2);
+
+            cf1 = supplyAsync(() -> 1);
+            cf2 = supplyAsync(() -> { cf3Done.arriveAndAwaitAdvance(); return 2; });
+            cf3 = cf1.applyToEitherAsync(cf2, (x) -> { check(x == 1); return x; });
+            checkCompletedNormally(cf3, 1);
+            checkCompletedNormally(cf1, 1);
+            check(!cf2.isDone());
+            cf3Done.arrive();
+            checkCompletedNormally(cf2, 2);
+            checkCompletedNormally(cf3, 1);
         } catch (Throwable t) { unexpected(t); }
 
         //----------------------------------------------------------------
@@ -570,6 +591,27 @@
             cf3 = cf2.acceptEitherAsync(cf1, (x) -> { fail(); });
             checkCompletedExceptionally(cf3);
             check(cf1.isDone() || cf2.isDone());
+
+            final Phaser cf3Done = new Phaser(2);
+            cf1 = supplyAsync(() -> { cf3Done.arriveAndAwaitAdvance(); return 1; });
+            cf2 = supplyAsync(() -> 2);
+            cf3 = cf1.acceptEither(cf2, (x) -> { check(x == 2); });
+            checkCompletedNormally(cf3, null);
+            checkCompletedNormally(cf2, 2);
+            check(!cf1.isDone());
+            cf3Done.arrive();
+            checkCompletedNormally(cf1, 1);
+            checkCompletedNormally(cf3, null);
+
+            cf1 = supplyAsync(() -> 1);
+            cf2 = supplyAsync(() -> { cf3Done.arriveAndAwaitAdvance(); return 2; });
+            cf3 = cf1.acceptEitherAsync(cf2, (x) -> { check(x == 1); });
+            checkCompletedNormally(cf3, null);
+            checkCompletedNormally(cf1, 1);
+            check(!cf2.isDone());
+            cf3Done.arrive();
+            checkCompletedNormally(cf2, 2);
+            checkCompletedNormally(cf3, null);
         } catch (Throwable t) { unexpected(t); }
 
         //----------------------------------------------------------------
@@ -605,19 +647,23 @@
             cf1 = runAsync(() -> { throw new RuntimeException(); });
             cf2 = runAsync(() -> { });
             cf3 = cf2.runAfterEither(cf1, () -> { atomicInt.incrementAndGet(); });
-            try { check(cf3.join() == null); } catch (CompletionException x) { pass(); }
+            try {
+                check(cf3.join() == null);
+                check(atomicInt.get() == (before + 1));
+            } catch (CompletionException x) { pass(); }
             check(cf3.isDone());
             check(cf1.isDone() || cf2.isDone());
-            check(atomicInt.get() == (before + 1));
 
             before = atomicInt.get();
             cf1 = runAsync(() -> { });
             cf2 = runAsync(() -> { throw new RuntimeException(); });
             cf3 = cf1.runAfterEitherAsync(cf2, () -> { atomicInt.incrementAndGet(); });
-            try { check(cf3.join() == null); } catch (CompletionException x) { pass(); }
+            try {
+                check(cf3.join() == null);
+                check(atomicInt.get() == (before + 1));
+            } catch (CompletionException x) { pass(); }
             check(cf3.isDone());
             check(cf1.isDone() || cf2.isDone());
-            check(atomicInt.get() == (before + 1));
 
             before = atomicInt.get();
             cf1 = runAsync(() -> { throw new RuntimeException(); });
@@ -626,6 +672,31 @@
             checkCompletedExceptionally(cf3);
             check(cf1.isDone() || cf2.isDone());
             check(atomicInt.get() == before);
+
+            final Phaser cf3Done = new Phaser(2);
+            before = atomicInt.get();
+            cf1 = runAsync(() -> { cf3Done.arriveAndAwaitAdvance(); });
+            cf2 = runAsync(() -> { });
+            cf3 = cf1.runAfterEither(cf2, () -> { atomicInt.incrementAndGet(); });
+            checkCompletedNormally(cf3, null);
+            checkCompletedNormally(cf2, null);
+            check(!cf1.isDone());
+            check(atomicInt.get() == (before + 1));
+            cf3Done.arrive();
+            checkCompletedNormally(cf1, null);
+            checkCompletedNormally(cf3, null);
+
+            before = atomicInt.get();
+            cf1 = runAsync(() -> { });
+            cf2 = runAsync(() -> { cf3Done.arriveAndAwaitAdvance(); });
+            cf3 = cf1.runAfterEitherAsync(cf2, () -> { atomicInt.incrementAndGet(); });
+            checkCompletedNormally(cf3, null);
+            checkCompletedNormally(cf1, null);
+            check(!cf2.isDone());
+            check(atomicInt.get() == (before + 1));
+            cf3Done.arrive();
+            checkCompletedNormally(cf2, null);
+            checkCompletedNormally(cf3, null);
         } catch (Throwable t) { unexpected(t); }
 
         //----------------------------------------------------------------