SocketInheritance.java revision 0:37a05a11f281
155714Skris/* 255714Skris * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. 355714Skris * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 455714Skris * 555714Skris * This code is free software; you can redistribute it and/or modify it 655714Skris * under the terms of the GNU General Public License version 2 only, as 755714Skris * published by the Free Software Foundation. 8280304Sjkim * 955714Skris * This code is distributed in the hope that it will be useful, but WITHOUT 1055714Skris * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1155714Skris * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1255714Skris * version 2 for more details (a copy is included in the LICENSE file that 1355714Skris * accompanied this code). 1455714Skris * 15280304Sjkim * You should have received a copy of the GNU General Public License version 1655714Skris * 2 along with this work; if not, write to the Free Software Foundation, 1755714Skris * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1855714Skris * 1955714Skris * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 2055714Skris * CA 95054 USA or visit www.sun.com if you need additional information or 2155714Skris * have any questions. 22280304Sjkim */ 2355714Skris 2455714Skris/* 2555714Skris * @test 2655714Skris * @summary Sockets shouldn't be inherited when creating a child process 2755714Skris */ 2855714Skrisimport java.nio.ByteBuffer; 2955714Skrisimport java.nio.channels.*; 3055714Skrisimport java.net.*; 3155714Skrisimport java.io.*; 3255714Skris 3355714Skrispublic class SocketInheritance { 3455714Skris 3555714Skris /* 3655714Skris * Simple helper class to direct process output to the parent 37280304Sjkim * System.out 3855714Skris */ 3955714Skris static class IOHandler implements Runnable { 40280304Sjkim InputStream in; 4155714Skris 4255714Skris IOHandler(InputStream in) { 4355714Skris this.in = in; 4455714Skris } 4555714Skris 4655714Skris static void handle(InputStream in) { 4755714Skris IOHandler handler = new IOHandler(in); 4855714Skris Thread thr = new Thread(handler); 4955714Skris thr.setDaemon(true); 5055714Skris thr.start(); 5155714Skris } 52280304Sjkim 5355714Skris public void run() { 5455714Skris try { 5555714Skris byte b[] = new byte[100]; 5655714Skris for (;;) { 5755714Skris int n = in.read(b); 5855714Skris if (n < 0) return; 5955714Skris System.out.write(b, 0, n); 60160814Ssimon } 6155714Skris } catch (IOException ioe) { } 6255714Skris } 6355714Skris 6455714Skris } 65194206Ssimon 6655714Skris // connect to the given port 6755714Skris static SocketChannel connect(int port) throws IOException { 68280304Sjkim InetAddress lh = InetAddress.getByName("127.0.0.1"); 69280304Sjkim InetSocketAddress isa = new InetSocketAddress(lh, port); 70280304Sjkim return SocketChannel.open(isa); 7155714Skris } 72280304Sjkim 73280304Sjkim // simple child process that handshakes with the parent and then 7455714Skris // waits indefinitely until it is destroyed 75280304Sjkim static void child(int port) { 76280304Sjkim try { 77280304Sjkim connect(port).close(); 7855714Skris } catch (IOException x) { 79280304Sjkim x.printStackTrace(); 80280304Sjkim return; 81280304Sjkim } 82280304Sjkim 8355714Skris for (;;) { 84280304Sjkim try { 85280304Sjkim Thread.sleep(10*1000); 86280304Sjkim } catch (InterruptedException x) { } 8755714Skris } 8855714Skris } 89280304Sjkim 90280304Sjkim 91280304Sjkim // Creates a loopback connection. 92280304Sjkim // Forks process which should not inherit the sockets. 93280304Sjkim // Close the sockets, and attempt to re-bind the listener. 94280304Sjkim 95280304Sjkim static void start() throws Exception { 9655714Skris 97280304Sjkim // setup loopback connection 98280304Sjkim ServerSocketChannel ssc = ServerSocketChannel.open(); 99280304Sjkim ssc.socket().bind( new InetSocketAddress(0) ); 100280304Sjkim 10155714Skris int port = ssc.socket().getLocalPort(); 102280304Sjkim 103280304Sjkim SocketChannel sc1 = connect(port); 104280304Sjkim SocketChannel sc2 = ssc.accept(); 105280304Sjkim 106280304Sjkim // launch the child 107280304Sjkim String cmd = System.getProperty("java.home") + File.separator + "bin" + 108280304Sjkim File.separator + "java SocketInheritance -child " + port; 109280304Sjkim 110280304Sjkim Process p = Runtime.getRuntime().exec(cmd); 11155714Skris 112280304Sjkim IOHandler.handle(p.getInputStream()); 113280304Sjkim IOHandler.handle(p.getErrorStream()); 114280304Sjkim 115280304Sjkim // wait for child to connect 116280304Sjkim SocketChannel sc3 = ssc.accept(); 117280304Sjkim 118280304Sjkim // close sockets 119280304Sjkim sc1.close(); 120280304Sjkim sc2.close(); 121280304Sjkim sc3.close(); 122280304Sjkim ssc.close(); 123280304Sjkim 124280304Sjkim // re-bind the listener - if the sockets were inherited then 125280304Sjkim // this will fail 126280304Sjkim try { 127280304Sjkim ssc = ServerSocketChannel.open(); 128280304Sjkim ssc.socket().bind(new InetSocketAddress(port)); 129280304Sjkim ssc.close(); 130280304Sjkim } finally { 131280304Sjkim p.destroy(); 132280304Sjkim } 133280304Sjkim 134280304Sjkim } 135280304Sjkim 136280304Sjkim public static void main(String[] args) throws Exception { 137280304Sjkim if (!System.getProperty("os.name").startsWith("Windows")) 138280304Sjkim return; 139280304Sjkim 140280304Sjkim if (args.length == 0) { 141280304Sjkim start(); 142280304Sjkim } else { 143280304Sjkim if (args[0].equals("-child")) { 144280304Sjkim child(Integer.parseInt(args[1])); 145280304Sjkim } 146280304Sjkim } 147280304Sjkim } 148280304Sjkim} 149280304Sjkim