|
1 /* |
|
2 * Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
21 * have any questions. |
|
22 */ |
|
23 |
|
24 /* @test |
|
25 * @bug 6403933 |
|
26 * @summary POLLHUP or POLLERR on "idle" key can cause Selector to spin |
|
27 */ |
|
28 |
|
29 import java.io.*; |
|
30 import java.net.*; |
|
31 import java.nio.*; |
|
32 import java.nio.channels.*; |
|
33 import java.net.*; |
|
34 import java.nio.channels.*; |
|
35 |
|
36 public class CloseWhenKeyIdle { |
|
37 |
|
38 // indicates if the wakeup has happened |
|
39 static volatile boolean wakeupDone = false; |
|
40 |
|
41 // Wakes up a Selector after a given delay |
|
42 static class Waker implements Runnable { |
|
43 private Selector sel; |
|
44 private long delay; |
|
45 |
|
46 Waker(Selector sel, long delay) { |
|
47 this.sel = sel; |
|
48 this.delay = delay; |
|
49 } |
|
50 |
|
51 public void run() { |
|
52 try { |
|
53 Thread.sleep(delay); |
|
54 wakeupDone = true; |
|
55 sel.wakeup(); |
|
56 } catch (Exception x) { |
|
57 x.printStackTrace(); |
|
58 } |
|
59 } |
|
60 } |
|
61 |
|
62 |
|
63 public static void main(String[] args) throws Exception { |
|
64 |
|
65 // Skip test on pre-2.6 kernels until the poll SelectorProvider |
|
66 // is updated |
|
67 String osname = System.getProperty("os.name"); |
|
68 if (osname.equals("Linux")) { |
|
69 String[] ver = System.getProperty("os.version").split("\\.", 0); |
|
70 if (ver.length >=2 ) { |
|
71 int major = Integer.parseInt(ver[0]); |
|
72 int minor = Integer.parseInt(ver[1]); |
|
73 if (major < 2 || (major == 2 && minor < 6)) { |
|
74 System.out.println("Test passing on pre-2.6 kernel"); |
|
75 return; |
|
76 } |
|
77 } |
|
78 } |
|
79 |
|
80 |
|
81 // establish loopback connection |
|
82 |
|
83 ServerSocketChannel ssc = ServerSocketChannel.open(); |
|
84 ssc.socket().bind(new InetSocketAddress(0)); |
|
85 |
|
86 SocketAddress remote = new InetSocketAddress(InetAddress.getLocalHost(), |
|
87 ssc.socket().getLocalPort()); |
|
88 |
|
89 SocketChannel sc1 = SocketChannel.open(remote); |
|
90 SocketChannel sc2 = ssc.accept(); |
|
91 |
|
92 // register channel for one end with a Selector, interest set = 0 |
|
93 |
|
94 Selector sel = Selector.open(); |
|
95 |
|
96 sc1.configureBlocking(false); |
|
97 SelectionKey k = sc1.register(sel, 0); |
|
98 sel.selectNow(); |
|
99 |
|
100 // hard close to provoke POLLHUP |
|
101 |
|
102 sc2.socket().setSoLinger(true, 0); |
|
103 sc2.close(); |
|
104 |
|
105 // schedule wakeup after a few seconds |
|
106 |
|
107 Thread t = new Thread(new Waker(sel, 5000)); |
|
108 t.setDaemon(true); |
|
109 t.start(); |
|
110 |
|
111 // select should block |
|
112 |
|
113 int spinCount = 0; |
|
114 for (;;) { |
|
115 int n = sel.select(); |
|
116 if (n > 0) |
|
117 throw new RuntimeException("channel should not be selected"); |
|
118 |
|
119 // wakeup |
|
120 if (wakeupDone) |
|
121 break; |
|
122 |
|
123 // wakeup for no reason - if it happens a few times then we have a |
|
124 // problem |
|
125 spinCount++; |
|
126 if (spinCount >= 3) |
|
127 throw new RuntimeException("Selector appears to be spinning"); |
|
128 } |
|
129 |
|
130 System.out.println("PASS"); |
|
131 } |
|
132 |
|
133 } |