1 /* 2 * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* @test 25 * @bug 6405995 26 * @summary Unit test for selector wakeup and interruption 27 * @library .. 28 * @key intermittent 29 */ 30 31 import java.io.*; 32 import java.net.*; 33 import java.nio.*; 34 import java.nio.channels.*; 35 import java.util.Random; 36 37 public class Wakeup { 38 39 static void sleep(int millis) { 40 try { 41 Thread.sleep(millis); 42 } catch (InterruptedException x) { 43 x.printStackTrace(); 44 } 45 } 46 47 static class Sleeper extends TestThread { 48 volatile boolean started = false; 49 volatile int entries = 0; 50 volatile int wakeups = 0; 51 volatile boolean wantInterrupt = false; 52 volatile boolean gotInterrupt = false; 53 volatile Exception exception = null; 54 volatile boolean closed = false; 55 Object gate = new Object(); 56 57 Selector sel; 58 59 Sleeper(Selector sel) { 60 super("Sleeper", System.err); 61 this.sel = sel; 62 } 63 64 public void go() throws Exception { 65 started = true; 66 for (;;) { 67 synchronized (gate) { } 68 entries++; 69 try { 70 sel.select(); 71 } catch (ClosedSelectorException x) { 72 closed = true; 73 } 74 boolean intr = Thread.currentThread().isInterrupted(); 75 wakeups++; 76 System.err.println("Wakeup " + wakeups 77 + (closed ? " (closed)" : "") 78 + (intr ? " (intr)" : "")); 79 if (wakeups > 1000) 80 throw new Exception("Too many wakeups"); 81 if (closed) 82 return; 83 if (wantInterrupt) { 84 while (!Thread.interrupted()) 85 Thread.yield(); 86 gotInterrupt = true; 87 wantInterrupt = false; 88 } 89 } 90 } 91 92 } 93 94 private static int checkedWakeups = 0; 95 96 private static void check(Sleeper sleeper, boolean intr) 97 throws Exception 98 { 99 checkedWakeups++; 100 if (sleeper.wakeups > checkedWakeups) { 101 sleeper.finish(100); 102 throw new Exception("Sleeper has run ahead"); 103 } 104 int n = 0; 105 while (sleeper.wakeups < checkedWakeups) { 106 sleep(50); 107 if ((n += 50) > 1000) { 108 sleeper.finish(100); 109 throw new Exception("Sleeper appears to be dead (" 110 + checkedWakeups + ")"); 111 } 112 } 113 if (sleeper.wakeups > checkedWakeups) { 114 sleeper.finish(100); 115 throw new Exception("Too many wakeups: Expected " 116 + checkedWakeups 117 + ", got " + sleeper.wakeups); 118 } 119 if (intr) { 120 n = 0; 121 // Interrupts can sometimes be delayed, so wait 122 while (!sleeper.gotInterrupt) { 123 sleep(50); 124 if ((n += 50) > 1000) { 125 sleeper.finish(100); 126 throw new Exception("Interrupt never delivered"); 127 } 128 } 129 sleeper.gotInterrupt = false; 130 } 131 System.err.println("Check " + checkedWakeups 132 + (intr ? " (intr " + n + ")" : "")); 133 } 134 135 public static void main(String[] args) throws Exception { 136 137 Selector sel = Selector.open(); 138 139 // Wakeup before select 140 sel.wakeup(); 141 142 Sleeper sleeper = new Sleeper(sel); 143 144 sleeper.start(); 145 while (!sleeper.started) 146 sleep(50); 147 148 check(sleeper, false); // 1 149 150 for (int i = 2; i < 5; i++) { 151 // Wakeup during select 152 sel.wakeup(); 153 check(sleeper, false); // 2 .. 4 154 } 155 156 // Double wakeup 157 synchronized (sleeper.gate) { 158 sel.wakeup(); 159 check(sleeper, false); // 5 160 sel.wakeup(); 161 sel.wakeup(); 162 } 163 check(sleeper, false); // 6 164 165 // Interrupt 166 synchronized (sleeper.gate) { 167 sleeper.wantInterrupt = true; 168 sleeper.interrupt(); 169 check(sleeper, true); // 7 170 } 171 172 // Interrupt before select 173 while (sleeper.entries < 8) 174 Thread.yield(); 175 synchronized (sleeper.gate) { 176 sel.wakeup(); 177 check(sleeper, false); // 8 178 sleeper.wantInterrupt = true; 179 sleeper.interrupt(); 180 sleep(50); 181 } 182 check(sleeper, true); // 9 183 184 // Close during select 185 while (sleeper.entries < 10) 186 Thread.yield(); 187 synchronized (sleeper.gate) { 188 sel.close(); 189 check(sleeper, false); // 10 190 } 191 192 if (sleeper.finish(200) == 0) 193 throw new Exception("Test failed"); 194 if (!sleeper.closed) 195 throw new Exception("Selector not closed"); 196 } 197 198 }