blob: eca929576cdc965ca5a9ef19ada6ea244e585db4 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2006 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 6285901
26 * @summary Check no data is written to wrong socket channel during async closing.
27 * @author Xueming Shen
28 */
29
30import java.io.*;
31import java.nio.*;
32import java.nio.channels.*;
33import java.net.*;
34
35public class AsyncCloseChannel {
36 static boolean failed = false;
37 static boolean keepGoing = true;
38 static String host = "127.0.0.1";
39 static int sensorPort = 3010;
40 static int targetPort = 3020;
41 static int maxAcceptCount = 1000;
42 static int acceptCount = 0;
43
44 public static void main(String args[]) throws Exception {
45 if (System.getProperty("os.name").startsWith("Windows")) {
46 System.err.println("WARNING: Still does not work on Windows!");
47 return;
48 }
49 Thread ss = new SensorServer(); ss.start();
50 Thread ts = new TargetServer(); ts.start();
51 Thread sc = new SensorClient(); sc.start();
52 Thread tc = new TargetClient(); tc.start();
53
54 while(acceptCount < maxAcceptCount && !failed) {
55 Thread.yield();
56 }
57 keepGoing = false;
58 try {
59 ss.interrupt();
60 ts.interrupt();
61 sc.interrupt();
62 tc.interrupt();
63 } catch (Exception e) {}
64 if (failed)
65 throw new RuntimeException("AsyncCloseChannel2 failed after <"
66 + acceptCount + "> times of accept!");
67 }
68
69
70 static class SensorServer extends ThreadEx {
71 public void runEx() throws Exception {
72 ServerSocket server;
73 server = new ServerSocket(sensorPort);
74 while(keepGoing) {
75 try {
76 final Socket s = server.accept();
77 new Thread() {
78 public void run() {
79 try {
80 int c = s.getInputStream().read();
81 if(c != -1) {
82 // No data is ever written to the peer's socket!
83 System.out.println("Oops: read a character: "
84 + (char) c);
85 failed = true;
86 }
87 } catch (IOException ex) {
88 ex.printStackTrace();
89 } finally {
90 closeIt(s);
91 }
92 }
93 }.start();
94 } catch (IOException ex) {
95 //ex.printStackTrace();
96 }
97 }
98 }
99 }
100
101 static class TargetServer extends ThreadEx {
102 public void runEx() throws Exception {
103
104 ServerSocket server;
105 server = new ServerSocket(targetPort);
106 while (keepGoing) {
107 try {
108 final Socket s = server.accept();
109 acceptCount++;
110 new Thread() {
111 public void run() {
112 boolean empty = true;
113 try {
114 for(;;) {
115 int c = s.getInputStream().read();
116 if(c == -1) {
117 if(!empty)
118 break;
119 }
120 empty = false;
121 }
122 } catch (IOException ex) {
123 ex.printStackTrace();
124 } finally {
125 closeIt(s);
126 }
127 }
128 }.start();
129 } catch (IOException ex) {
130 //ex.printStackTrace();
131 }
132 }
133 }
134 }
135
136 static class SensorClient extends Thread {
137 private static boolean wake;
138 private static SensorClient theClient;
139 public void run() {
140 while (keepGoing) {
141 Socket s = null;
142 try {
143 s = new Socket();
144 synchronized(this) {
145 while(!wake) {
146 try {
147 wait();
148 } catch (InterruptedException ex) { }
149 }
150 }
151 wake = false;
152 s.connect(new InetSocketAddress(host, sensorPort));
153 try {
154 Thread.sleep(10);
155 } catch (InterruptedException ex) { }
156 } catch (IOException ex) {
157 System.out.println("Exception on sensor client " + ex.getMessage());
158 } finally {
159 if(s != null) {
160 try {
161 s.close();
162 } catch(IOException ex) { ex.printStackTrace();}
163 }
164 }
165 }
166 }
167
168 public SensorClient() {
169 theClient = this;
170 }
171
172 public static void wakeMe() {
173 synchronized(theClient) {
174 wake = true;
175 theClient.notify();
176 }
177 }
178 }
179
180 static class TargetClient extends Thread {
181 volatile boolean ready = false;
182 public void run() {
183 while(keepGoing) {
184 try {
185 final SocketChannel s = SocketChannel.open(
186 new InetSocketAddress(host, targetPort));
187 s.finishConnect();
188 s.socket().setSoLinger(false, 0);
189 ready = false;
190 Thread t = new Thread() {
191 public void run() {
192 ByteBuffer b = ByteBuffer.allocate(1);
193 try {
194 for(;;) {
195 b.clear();
196 b.put((byte) 'A');
197 b.flip();
198 s.write(b);
199 ready = true;
200 }
201 } catch (IOException ex) {
202 if(!(ex instanceof ClosedChannelException))
203 System.out.println("Exception in target client child "
204 + ex.toString());
205 }
206 }
207 };
208 t.start();
209 while(!ready)
210 Thread.yield();
211 s.close();
212 SensorClient.wakeMe();
213 t.join();
214 } catch (IOException ex) {
215 System.out.println("Exception in target client parent "
216 + ex.getMessage());
217 } catch (InterruptedException ex) {}
218 }
219 }
220 }
221
222 static abstract class ThreadEx extends Thread {
223 public void run() {
224 try {
225 runEx();
226 } catch (Exception ex) {
227 ex.printStackTrace();
228 }
229 }
230
231 abstract void runEx() throws Exception;
232 }
233
234
235 public static void closeIt(Socket s) {
236 try {
237 if(s != null)
238 s.close();
239 } catch (IOException ex) { }
240 }
241}