1 /* 2 * Copyright (c) 1999, 2018, 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 8195160 26 * @summary Make sure a deadlock situation would not occur 27 * @requires (os.family == "linux") 28 * @library .. /test/lib 29 * @build RsocketTest 30 * @run main/othervm -Djava.net.preferIPv4Stack=true DeadlockTest 31 */ 32 import java.net.*; 33 import java.io.*; 34 import jdk.net.Sockets; 35 36 public class DeadlockTest { 37 public static void main(String [] argv) throws Exception { 38 if (!RsocketTest.isRsocketAvailable()) 39 return; 40 41 InetAddress addr = InetAddress.getLocalHost(); 42 ServerSocket ss = Sockets.openRdmaServerSocket(); 43 ss.bind(new InetSocketAddress(addr, 0)); 44 45 Socket clientSocket = Sockets.openRdmaSocket(); 46 47 try { 48 // Start the server thread 49 Thread s1 = new Thread(new ServerThread(ss)); 50 s1.start(); 51 52 // Start the client thread 53 ClientThread ct = new ClientThread(clientSocket, ss.getLocalPort()); 54 Thread c1 = new Thread(ct); 55 c1.start(); 56 57 // Wait for the client thread to finish 58 c1.join(20000); 59 60 // If timeout, we assume there is a deadlock 61 if (c1.isAlive() == true) { 62 // Close the socket to force the server thread 63 // terminate too 64 s1.stop(); 65 throw new Exception("Takes too long. Dead lock"); 66 } 67 } finally { 68 ss.close(); 69 clientSocket.close(); 70 } 71 } 72 } 73 74 class ServerThread implements Runnable { 75 76 private static boolean dbg = false; 77 78 ObjectInputStream in; 79 ObjectOutputStream out; 80 81 ServerSocket server; 82 83 Socket sock; 84 85 public ServerThread(ServerSocket serverSocket) throws Exception { 86 this.server = serverSocket; 87 } 88 89 public void ping(int cnt) { 90 Message.write(out, new PingMessage(cnt)); 91 } 92 93 private int cnt = 1; 94 95 public void run() { 96 97 try { 98 if (Thread.currentThread().getName().startsWith("child") == false) { 99 sock = server.accept(); 100 101 new Thread(this, "child").start(); 102 103 out = new ObjectOutputStream(sock.getOutputStream()); 104 out.flush(); 105 106 if (dbg) System.out.println("*** ping0 ***"); 107 ping(0); 108 if (dbg) System.out.println("*** ping1 ***"); 109 ping(1); 110 if (dbg) System.out.println("*** ping2 ***"); 111 ping(2); 112 if (dbg) System.out.println("*** ping3 ***"); 113 ping(3); 114 if (dbg) System.out.println("*** ping4 ***"); 115 ping(4); 116 if (dbg) System.out.println("*** end ***"); 117 } 118 119 } catch (Throwable e) { 120 System.out.println(e); 121 // If anything goes wrong, just quit. 122 } 123 124 if (Thread.currentThread().getName().startsWith("child")) { 125 try { 126 127 in = new ObjectInputStream(sock.getInputStream()); 128 129 while (true) { 130 if (dbg) System.out.println("read " + cnt); 131 Message msg = (Message) in.readObject(); 132 if (dbg) System.out.println("read done " + cnt++); 133 switch (msg.code) { 134 case Message.PING: { 135 if (true) System.out.println("ping recv'ed"); 136 } break; 137 } 138 139 } 140 141 } catch (Throwable e) { 142 // If anything goes wrong, just quit. } 143 } 144 } 145 } 146 } 147 148 class ClientThread implements Runnable { 149 150 ObjectInputStream in; 151 ObjectOutputStream out; 152 153 Socket sock; 154 155 public ClientThread(Socket sock, int serverPort) throws Exception { 156 try { 157 System.out.println("About to connect the client socket"); 158 this.sock = sock; 159 this.sock.connect(new InetSocketAddress(InetAddress.getLocalHost(), serverPort)); 160 System.out.println("connected"); 161 162 out = new ObjectOutputStream(sock.getOutputStream()); 163 out.flush(); 164 } catch (Throwable e) { 165 System.out.println("client failed with: " + e); 166 e.printStackTrace(); 167 throw new Exception("Unexpected exception"); 168 } 169 } 170 171 private int cnt = 1; 172 173 public void run() { 174 try { 175 in = new ObjectInputStream(sock.getInputStream()); 176 177 int count = 0; 178 179 while (true) { 180 System.out.println("read " + cnt); 181 Message msg = (Message) in.readObject(); 182 System.out.println("read done " + cnt++); 183 switch (msg.code) { 184 case Message.PING: { 185 System.out.println("ping recv'ed"); 186 count++; 187 } break; 188 } 189 if (count == 5) { 190 sock.close(); 191 break; 192 } 193 } 194 } catch (IOException ioe) { 195 } catch (Throwable e) { 196 // If anything went wrong, just quit 197 } 198 } 199 200 } 201 202 class Message implements java.io.Serializable { 203 204 static final int UNKNOWN = 0; 205 static final int PING = 1; 206 207 protected int code; 208 209 public Message() { this.code = UNKNOWN; } 210 211 public Message(int code) { this.code = code; } 212 213 private static int cnt = 1; 214 215 public static void write(ObjectOutput out, Message msg) { 216 try { 217 System.out.println("write message " + cnt); 218 out.writeObject(msg); 219 System.out.println("flush message"); 220 out.flush(); 221 System.out.println("write message done " + cnt++); 222 } catch (IOException ioe) { 223 // Ignore the exception 224 System.out.println(ioe); 225 } 226 } 227 } 228 229 class PingMessage extends Message implements java.io.Serializable { 230 231 public PingMessage() { 232 code = Message.PING; 233 } 234 235 public PingMessage(int cnt) 236 { 237 code = Message.PING; 238 this.cnt = cnt; 239 240 data = new int[50000]; 241 } 242 243 int cnt; 244 int[] data; 245 }