1 /* 2 * Copyright (c) 2003, 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 4531526 26 * @summary Test that more than one debuggee cannot bind to same port 27 * at the same time. 28 * 29 * @build VMConnection ExclusiveBind HelloWorld 30 * @run main ExclusiveBind 31 */ 32 import java.io.InputStream; 33 import java.io.IOException; 34 import java.io.File; 35 import java.net.ServerSocket; 36 import com.sun.jdi.Bootstrap; 37 import com.sun.jdi.VirtualMachine; 38 import com.sun.jdi.connect.Connector; 39 import com.sun.jdi.connect.AttachingConnector; 40 import java.util.Map; 41 import java.util.List; 42 import java.util.Iterator; 43 44 public class ExclusiveBind { 45 46 /* 47 * Helper class to direct process output to the parent 48 * System.out 49 */ 50 static class IOHandler implements Runnable { 51 InputStream in; 52 53 IOHandler(InputStream in) { 54 this.in = in; 55 } 56 57 static void handle(InputStream in) { 58 IOHandler handler = new IOHandler(in); 59 Thread thr = new Thread(handler); 60 thr.setDaemon(true); 61 thr.start(); 62 } 63 64 public void run() { 65 try { 66 byte b[] = new byte[100]; 67 for (;;) { 68 int n = in.read(b); 69 if (n < 0) return; 70 for (int i=0; i<n; i++) { 71 System.out.print((char)b[i]); 72 } 73 } 74 } catch (IOException ioe) { } 75 } 76 77 } 78 79 /* 80 * Find a connector by name 81 */ 82 private static Connector findConnector(String name) { 83 List connectors = Bootstrap.virtualMachineManager().allConnectors(); 84 Iterator iter = connectors.iterator(); 85 while (iter.hasNext()) { 86 Connector connector = (Connector)iter.next(); 87 if (connector.name().equals(name)) { 88 return connector; 89 } 90 } 91 return null; 92 } 93 94 /* 95 * Launch (in server mode) a debuggee with the given address and 96 * suspend mode. 97 */ 98 private static Process launch(String address, boolean suspend, String class_name) throws IOException { 99 String exe = System.getProperty("java.home") + File.separator + "bin" + 100 File.separator; 101 String arch = System.getProperty("os.arch"); 102 String osname = System.getProperty("os.name"); 103 if (osname.equals("SunOS") && arch.equals("sparcv9")) { 104 exe += "sparcv9/java"; 105 } else if (osname.equals("SunOS") && arch.equals("amd64")) { 106 exe += "amd64/java"; 107 } else { 108 exe += "java"; 109 } 110 String cmd = exe + " " + VMConnection.getDebuggeeVMOptions() + 111 " -agentlib:jdwp=transport=dt_socket,server=y,suspend="; 112 if (suspend) { 113 cmd += "y"; 114 } else { 115 cmd += "n"; 116 } 117 cmd += ",address=" + address + " " + class_name; 118 119 System.out.println("Starting: " + cmd); 120 121 Process p = Runtime.getRuntime().exec(cmd); 122 IOHandler.handle(p.getInputStream()); 123 IOHandler.handle(p.getErrorStream()); 124 125 return p; 126 } 127 128 /* 129 * - pick a TCP port 130 * - Launch a debuggee in server=y,suspend=y,address=${port} 131 * - Launch a second debuggee in server=y,suspend=n with the same port 132 * - Second debuggee should fail with an error (address already in use) 133 * - For clean-up we attach to the first debuggee and resume it. 134 */ 135 public static void main(String args[]) throws Exception { 136 // find a free port 137 ServerSocket ss = new ServerSocket(0); 138 int port = ss.getLocalPort(); 139 ss.close(); 140 141 String address = String.valueOf(port); 142 143 // launch the first debuggee 144 Process process1 = launch(address, true, "HelloWorld"); 145 146 // give first debuggee time to suspend 147 Thread.currentThread().sleep(5000); 148 149 // launch a second debuggee with the same address 150 Process process2 = launch(address, false, "HelloWorld"); 151 152 // get exit status from second debuggee 153 int exitCode = process2.waitFor(); 154 155 // clean-up - attach to first debuggee and resume it 156 AttachingConnector conn = (AttachingConnector)findConnector("com.sun.jdi.SocketAttach"); 157 Map conn_args = conn.defaultArguments(); 158 Connector.IntegerArgument port_arg = 159 (Connector.IntegerArgument)conn_args.get("port"); 160 port_arg.setValue(port); 161 VirtualMachine vm = conn.attach(conn_args); 162 vm.resume(); 163 164 // if the second debuggee ran to completion then we've got a problem 165 if (exitCode == 0) { 166 throw new RuntimeException("Test failed - second debuggee didn't fail to bind"); 167 } else { 168 System.out.println("Test passed - second debuggee correctly failed to bind"); 169 } 170 } 171 }