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 }