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