1 /* 2 * Copyright (c) 2005, 2006, 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 6306165 6432567 26 * @summary Check that a bad handshake doesn't cause a debuggee to abort 27 * 28 * @build VMConnection BadHandshakeTest Exit0 29 * @run main BadHandshakeTest 30 * 31 */ 32 import java.io.InputStream; 33 import java.io.IOException; 34 import java.io.File; 35 import java.io.BufferedInputStream; 36 import java.net.ServerSocket; 37 import java.net.Socket; 38 import java.net.InetAddress; 39 import com.sun.jdi.Bootstrap; 40 import com.sun.jdi.VirtualMachine; 41 import com.sun.jdi.event.*; 42 import com.sun.jdi.connect.Connector; 43 import com.sun.jdi.connect.AttachingConnector; 44 import java.util.Map; 45 import java.util.List; 46 import java.util.Iterator; 47 48 public class BadHandshakeTest { 49 50 static volatile boolean ready = false; 51 52 /* 53 * Helper class to redirect process output/error 54 */ 55 static class IOHandler implements Runnable { 56 InputStream in; 57 58 IOHandler(InputStream in) { 59 this.in = in; 60 } 61 62 static void handle(InputStream in) { 63 IOHandler handler = new IOHandler(in); 64 Thread thr = new Thread(handler); 65 thr.setDaemon(true); 66 thr.start(); 67 } 68 69 public void run() { 70 try { 71 byte b[] = new byte[100]; 72 for (;;) { 73 int n = in.read(b, 0, 100); 74 // The first thing that will get read is 75 // Listening for transport dt_socket at address: xxxxx 76 // which shows the debuggee is ready to accept connections. 77 ready = true; 78 if (n < 0) { 79 break; 80 } 81 String s = new String(b, 0, n, "UTF-8"); 82 System.out.print(s); 83 } 84 } catch (IOException ioe) { 85 ioe.printStackTrace(); 86 } 87 } 88 89 } 90 91 /* 92 * Find a connector by name 93 */ 94 private static Connector findConnector(String name) { 95 List connectors = Bootstrap.virtualMachineManager().allConnectors(); 96 Iterator iter = connectors.iterator(); 97 while (iter.hasNext()) { 98 Connector connector = (Connector)iter.next(); 99 if (connector.name().equals(name)) { 100 return connector; 101 } 102 } 103 return null; 104 } 105 106 /* 107 * Launch a server debuggee with the given address 108 */ 109 private static Process launch(String address, String class_name) throws IOException { 110 String exe = System.getProperty("java.home") 111 + File.separator + "bin" + File.separator; 112 String arch = System.getProperty("os.arch"); 113 String osname = System.getProperty("os.name"); 114 if (osname.equals("SunOS") && arch.equals("sparcv9")) { 115 exe += "sparcv9/java"; 116 } else if (osname.equals("SunOS") && arch.equals("amd64")) { 117 exe += "amd64/java"; 118 } else { 119 exe += "java"; 120 } 121 String cmd = exe + " " + VMConnection.getDebuggeeVMOptions() + 122 " -agentlib:jdwp=transport=dt_socket" + 123 ",server=y" + ",suspend=y" + ",address=" + address + 124 " " + class_name; 125 126 System.out.println("Starting: " + cmd); 127 128 Process p = Runtime.getRuntime().exec(cmd); 129 130 IOHandler.handle(p.getInputStream()); 131 IOHandler.handle(p.getErrorStream()); 132 133 return p; 134 } 135 136 /* 137 * - pick a TCP port 138 * - Launch a server debuggee: server=y,suspend=y,address=${port} 139 * - run it to VM death 140 * - verify we saw no error 141 */ 142 public static void main(String args[]) throws Exception { 143 // find a free port 144 ServerSocket ss = new ServerSocket(0); 145 int port = ss.getLocalPort(); 146 ss.close(); 147 148 String address = String.valueOf(port); 149 150 // launch the server debuggee 151 Process process = launch(address, "Exit0"); 152 153 // wait for the debugge to be ready 154 while (!ready) { 155 try { 156 Thread.sleep(1000); 157 } catch(Exception ee) { 158 throw ee; 159 } 160 } 161 162 // Connect to the debuggee and handshake with garbage 163 Socket s = new Socket(InetAddress.getLocalHost(), port); 164 s.getOutputStream().write("Here's a poke in the eye".getBytes("UTF-8")); 165 s.close(); 166 167 // Re-connect and to a partial handshake - don't disconnect 168 s = new Socket(InetAddress.getLocalHost(), port); 169 s.getOutputStream().write("JDWP-".getBytes("UTF-8")); 170 171 172 // attach to server debuggee and resume it so it can exit 173 AttachingConnector conn = (AttachingConnector)findConnector("com.sun.jdi.SocketAttach"); 174 Map conn_args = conn.defaultArguments(); 175 Connector.IntegerArgument port_arg = 176 (Connector.IntegerArgument)conn_args.get("port"); 177 port_arg.setValue(port); 178 VirtualMachine vm = conn.attach(conn_args); 179 180 // The first event is always a VMStartEvent, and it is always in 181 // an EventSet by itself. Wait for it. 182 EventSet evtSet = vm.eventQueue().remove(); 183 for (Event event: evtSet) { 184 if (event instanceof VMStartEvent) { 185 break; 186 } 187 throw new RuntimeException("Test failed - debuggee did not start properly"); 188 } 189 190 vm.eventRequestManager().deleteAllBreakpoints(); 191 vm.resume(); 192 193 process.waitFor(); 194 } 195 196 }