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 */ 29 30 import java.nio.channels.*; 31 32 public class Wakeup { 33 34 static void sleep(int millis) { 35 try { 36 Thread.sleep(millis); 37 } catch (InterruptedException x) { 38 x.printStackTrace(); 39 } 40 } 41 42 static class Sleeper extends TestThread { 43 volatile boolean started = false; 44 volatile int entries = 0; 45 volatile int wakeups = 0; 46 volatile boolean wantInterrupt = false; 47 volatile boolean gotInterrupt = false; 48 volatile Exception exception = null; 49 volatile boolean closed = false; 50 Object gate = new Object(); 51 52 Selector sel; 53 54 Sleeper(Selector sel) { 55 super("Sleeper", System.err); 56 this.sel = sel; 57 } 58 59 public void go() throws Exception { 60 started = true; 61 for (;;) { 62 synchronized (gate) { } 63 entries++; 64 try { 65 sel.select(); 66 } catch (ClosedSelectorException x) { 67 closed = true; 68 } 69 boolean intr = Thread.currentThread().isInterrupted(); 70 wakeups++; 71 System.err.println("Wakeup " + wakeups 72 + (closed ? " (closed)" : "") 73 + (intr ? " (intr)" : "")); 74 if (wakeups > 1000) 75 throw new Exception("Too many wakeups"); 76 if (closed) 77 return; 78 if (wantInterrupt) { 79 while (!Thread.interrupted()) 80 Thread.yield(); 81 gotInterrupt = true; 82 wantInterrupt = false; 83 } 84 } 85 } 86 87 } 88 89 private static int checkedWakeups = 0; 90 91 private static void check(Sleeper sleeper, boolean intr) 92 throws Exception 93 { 94 checkedWakeups++; 95 if (sleeper.wakeups > checkedWakeups) { 96 sleeper.finish(100); 97 throw new Exception("Sleeper has run ahead"); 98 } 99 int n = 0; 100 while (sleeper.wakeups < checkedWakeups) { 101 sleep(1); 102 if ((n += 1) > 3000) { 103 sleeper.finish(100); 104 throw new Exception("Sleeper appears to be dead (" 105 + checkedWakeups + ")"); 106 } 107 } 108 if (sleeper.wakeups > checkedWakeups) { 109 sleeper.finish(100); 110 throw new Exception("Too many wakeups: Expected " 111 + checkedWakeups 112 + ", got " + sleeper.wakeups); 113 } 114 if (intr) { 115 n = 0; 116 // Interrupts can sometimes be delayed, so wait 117 while (!sleeper.gotInterrupt) { 118 sleep(50); 119 if ((n += 50) > 3000) { 120 sleeper.finish(100); 121 throw new Exception("Interrupt never delivered"); 122 } 123 } 124 sleeper.gotInterrupt = false; 125 } 126 System.err.println("Check " + checkedWakeups 127 + (intr ? " (intr " + n + ")" : "")); 128 } 129 130 public static void main(String[] args) throws Exception { 131 132 Selector sel = Selector.open(); 133 134 // Wakeup before select 135 sel.wakeup(); 136 137 Sleeper sleeper = new Sleeper(sel); 138 139 sleeper.start(); 140 while (!sleeper.started) 141 sleep(50); 142 143 check(sleeper, false); // 1 144 145 for (int i = 2; i < 5; i++) { 146 // Wakeup during select 147 sel.wakeup(); 148 check(sleeper, false); // 2 .. 4 149 } 150 151 while (sleeper.entries < 5) 152 Thread.yield(); 153 // Double wakeup 154 synchronized (sleeper.gate) { 155 sel.wakeup(); 156 check(sleeper, false); // 5 157 sel.wakeup(); 158 sel.wakeup(); 159 } 160 check(sleeper, false); // 6 161 162 while (sleeper.entries < 7) 163 Thread.yield(); 164 // Interrupt 165 synchronized (sleeper.gate) { 166 sleeper.wantInterrupt = true; 167 sleeper.interrupt(); 168 check(sleeper, true); // 7 169 } 170 171 // Interrupt before select 172 while (sleeper.entries < 8) 173 Thread.yield(); 174 synchronized (sleeper.gate) { 175 sel.wakeup(); 176 check(sleeper, false); // 8 177 sleeper.wantInterrupt = true; 178 sleeper.interrupt(); 179 sleep(50); 180 } 181 check(sleeper, true); // 9 182 183 // Close during select 184 while (sleeper.entries < 10) 185 Thread.yield(); 186 synchronized (sleeper.gate) { 187 sel.close(); 188 check(sleeper, false); // 10 189 } 190 191 if (sleeper.finish(200) == 0) 192 throw new Exception("Test failed"); 193 if (!sleeper.closed) 194 throw new Exception("Selector not closed"); 195 } 196 197 }