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