changeset 417:0844644a266a

Merge
author alanb
date Tue, 22 Jul 2008 09:19:38 +0100
parents 2e537136b40e 9a01bb6b5cc8
children 73d1cb15b323
files
diffstat 4 files changed, 221 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/nio/channels/SelectionKey.java	Tue Jul 15 15:09:41 2008 +0100
+++ b/src/share/classes/java/nio/channels/SelectionKey.java	Tue Jul 22 09:19:38 2008 +0100
@@ -191,7 +191,7 @@
      * @throws  IllegalArgumentException
      *          If a bit in the set does not correspond to an operation that
      *          is supported by this key's channel, that is, if
-     *          <tt>set & ~(channel().validOps()) != 0</tt>
+     *          <tt>(ops & ~channel().validOps()) != 0</tt>
      *
      * @throws  CancelledKeyException
      *          If this key has been cancelled
--- a/src/share/classes/sun/nio/ch/SelectorImpl.java	Tue Jul 15 15:09:41 2008 +0100
+++ b/src/share/classes/sun/nio/ch/SelectorImpl.java	Tue Jul 22 09:19:38 2008 +0100
@@ -142,18 +142,20 @@
         // Precondition: Synchronized on this, keys, and selectedKeys
         Set cks = cancelledKeys();
         synchronized (cks) {
-            Iterator i = cks.iterator();
-            while (i.hasNext()) {
-                SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
-                try {
-                    implDereg(ski);
-                } catch (SocketException se) {
-                    IOException ioe = new IOException(
-                        "Error deregistering key");
-                    ioe.initCause(se);
-                    throw ioe;
-                } finally {
-                    i.remove();
+            if (!cks.isEmpty()) {
+                Iterator i = cks.iterator();
+                while (i.hasNext()) {
+                    SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
+                    try {
+                        implDereg(ski);
+                    } catch (SocketException se) {
+                        IOException ioe = new IOException(
+                            "Error deregistering key");
+                        ioe.initCause(se);
+                        throw ioe;
+                    } finally {
+                        i.remove();
+                    }
                 }
             }
         }
--- a/test/java/nio/channels/FileChannel/ExpandingMap.java	Tue Jul 15 15:09:41 2008 +0100
+++ b/test/java/nio/channels/FileChannel/ExpandingMap.java	Tue Jul 22 09:19:38 2008 +0100
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4938372
+ * @bug 4938372 6541641
  * @summary Flushing dirty pages prior to unmap can cause Cleaner thread to
  *          abort VM if memory system has pages locked
  */
@@ -39,7 +39,7 @@
 
 public class ExpandingMap {
 
-    public static void main(String[] args) throws IOException {
+    public static void main(String[] args) throws Exception {
 
         int initialSize = 20480*1024;
         int maximumMapSize = 16*1024*1024;
@@ -103,6 +103,13 @@
             }
         }
 
+        fc.close();
+        // cleanup the ref to mapped buffers so they can be GCed
+        for (int i = 0; i < buffers.length; i++)
+            buffers[i] = null;
+        System.gc();
+        // Take a nap to wait for the Cleaner to cleanup those unrefed maps
+        Thread.sleep(1000);
         System.out.println("TEST PASSED");
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/nio/channels/Selector/Wakeup.java	Tue Jul 22 09:19:38 2008 +0100
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2001-2003 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @bug 6405995
+ * @summary Unit test for selector wakeup and interruption
+ * @library ..
+ */
+
+import java.io.*;
+import java.net.*;
+import java.nio.*;
+import java.nio.channels.*;
+import java.util.Random;
+
+public class Wakeup {
+
+    static void sleep(int millis) {
+        try {
+            Thread.sleep(millis);
+        } catch (InterruptedException x) {
+            x.printStackTrace();
+        }
+    }
+
+    static class Sleeper extends TestThread {
+        volatile boolean started = false;
+        volatile int entries = 0;
+        volatile int wakeups = 0;
+        volatile boolean wantInterrupt = false;
+        volatile boolean gotInterrupt = false;
+        volatile Exception exception = null;
+        volatile boolean closed = false;
+        Object gate = new Object();
+
+        Selector sel;
+
+        Sleeper(Selector sel) {
+            super("Sleeper", System.err);
+            this.sel = sel;
+        }
+
+        public void go() throws Exception {
+            started = true;
+            for (;;) {
+                synchronized (gate) { }
+                entries++;
+                try {
+                    sel.select();
+                } catch (ClosedSelectorException x) {
+                    closed = true;
+                }
+                boolean intr = Thread.currentThread().isInterrupted();
+                wakeups++;
+                System.err.println("Wakeup " + wakeups
+                                   + (closed ? " (closed)" : "")
+                                   + (intr ? " (intr)" : ""));
+                if (wakeups > 1000)
+                    throw new Exception("Too many wakeups");
+                if (closed)
+                    return;
+                if (wantInterrupt) {
+                    while (!Thread.interrupted())
+                        Thread.yield();
+                    gotInterrupt = true;
+                    wantInterrupt = false;
+                }
+            }
+        }
+
+    }
+
+    private static int checkedWakeups = 0;
+
+    private static void check(Sleeper sleeper, boolean intr)
+        throws Exception
+    {
+        checkedWakeups++;
+        if (sleeper.wakeups > checkedWakeups) {
+            sleeper.finish(100);
+            throw new Exception("Sleeper has run ahead");
+        }
+        int n = 0;
+        while (sleeper.wakeups < checkedWakeups) {
+            sleep(50);
+            if ((n += 50) > 1000) {
+                sleeper.finish(100);
+                throw new Exception("Sleeper appears to be dead ("
+                                    + checkedWakeups + ")");
+            }
+        }
+        if (sleeper.wakeups > checkedWakeups) {
+            sleeper.finish(100);
+            throw new Exception("Too many wakeups: Expected "
+                                + checkedWakeups
+                                + ", got " + sleeper.wakeups);
+        }
+        if (intr) {
+            n = 0;
+            // Interrupts can sometimes be delayed, so wait
+            while (!sleeper.gotInterrupt) {
+                sleep(50);
+                if ((n += 50) > 1000) {
+                    sleeper.finish(100);
+                    throw new Exception("Interrupt never delivered");
+                }
+            }
+            sleeper.gotInterrupt = false;
+        }
+        System.err.println("Check " + checkedWakeups
+                           + (intr ? " (intr " + n + ")" : ""));
+    }
+
+    public static void main(String[] args) throws Exception {
+
+        Selector sel = Selector.open();
+
+        // Wakeup before select
+        sel.wakeup();
+
+        Sleeper sleeper = new Sleeper(sel);
+
+        sleeper.start();
+        while (!sleeper.started)
+            sleep(50);
+
+        check(sleeper, false);          // 1
+
+        for (int i = 2; i < 5; i++) {
+            // Wakeup during select
+            sel.wakeup();
+            check(sleeper, false);      // 2 .. 4
+        }
+
+        // Double wakeup
+        synchronized (sleeper.gate) {
+            sel.wakeup();
+            check(sleeper, false);      // 5
+            sel.wakeup();
+            sel.wakeup();
+        }
+        check(sleeper, false);          // 6
+
+        // Interrupt
+        synchronized (sleeper.gate) {
+            sleeper.wantInterrupt = true;
+            sleeper.interrupt();
+            check(sleeper, true);       // 7
+        }
+
+        // Interrupt before select
+        while (sleeper.entries < 8)
+            Thread.yield();
+        synchronized (sleeper.gate) {
+            sel.wakeup();
+            check(sleeper, false);      // 8
+            sleeper.wantInterrupt = true;
+            sleeper.interrupt();
+            sleep(50);
+        }
+        check(sleeper, true);           // 9
+
+        // Close during select
+        while (sleeper.entries < 10)
+            Thread.yield();
+        synchronized (sleeper.gate) {
+            sel.close();
+            check(sleeper, false);      // 10
+        }
+
+        if (sleeper.finish(200) == 0)
+            throw new Exception("Test failed");
+        if (!sleeper.closed)
+            throw new Exception("Selector not closed");
+    }
+
+}