SocketInheritance.java revision 2546:eb84b89ef3ff
1/*
2 * Copyright (c) 2007, 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/*
25 * @test
26 * @summary Sockets shouldn't be inherited when creating a child process
27 */
28import java.nio.ByteBuffer;
29import java.nio.channels.*;
30import java.net.*;
31import java.io.*;
32
33public class SocketInheritance {
34
35    /*
36     * Simple helper class to direct process output to the parent
37     * System.out
38     */
39    static class IOHandler implements Runnable {
40        InputStream in;
41
42        IOHandler(InputStream in) {
43            this.in = in;
44        }
45
46        static void handle(InputStream in) {
47            IOHandler handler = new IOHandler(in);
48            Thread thr = new Thread(handler);
49            thr.setDaemon(true);
50            thr.start();
51        }
52
53        public void run() {
54            try {
55                byte b[] = new byte[100];
56                for (;;) {
57                    int n = in.read(b);
58                    if (n < 0) return;
59                    System.out.write(b, 0, n);
60                }
61            } catch (IOException ioe) { }
62        }
63
64    }
65
66    // connect to the given port
67    static SocketChannel connect(int port) throws IOException {
68        InetAddress lh = InetAddress.getByName("127.0.0.1");
69        InetSocketAddress isa = new InetSocketAddress(lh, port);
70        return SocketChannel.open(isa);
71    }
72
73    // simple child process that handshakes with the parent and then
74    // waits indefinitely until it is destroyed
75    static void child(int port) {
76        try {
77            connect(port).close();
78        } catch (IOException x) {
79            x.printStackTrace();
80            return;
81        }
82
83        for (;;) {
84            try {
85                Thread.sleep(10*1000);
86            } catch (InterruptedException x) { }
87        }
88    }
89
90
91    // Creates a loopback connection.
92    // Forks process which should not inherit the sockets.
93    // Close the sockets, and attempt to re-bind the listener.
94
95    static void start() throws Exception {
96
97        // setup loopback connection
98        ServerSocketChannel ssc = ServerSocketChannel.open();
99        ssc.socket().bind( new InetSocketAddress(0) );
100
101        int port = ssc.socket().getLocalPort();
102
103        SocketChannel sc1 = connect(port);
104        SocketChannel sc2 = ssc.accept();
105
106        // launch the child
107        String cmd = System.getProperty("java.home") + File.separator + "bin" +
108            File.separator + "java";
109        String testClasses = System.getProperty("test.classes");
110        if (testClasses != null)
111            cmd += " -cp " + testClasses;
112        cmd += " SocketInheritance -child " + port;
113
114        Process p = Runtime.getRuntime().exec(cmd);
115
116        IOHandler.handle(p.getInputStream());
117        IOHandler.handle(p.getErrorStream());
118
119        // wait for child to connect
120        SocketChannel sc3 = ssc.accept();
121
122        // close sockets
123        sc1.close();
124        sc2.close();
125        sc3.close();
126        ssc.close();
127
128        // re-bind the listener - if the sockets were inherited then
129        // this will fail
130        try {
131            ssc = ServerSocketChannel.open();
132            ssc.socket().bind(new InetSocketAddress(port));
133            ssc.close();
134        } finally {
135            p.destroy();
136        }
137
138    }
139
140    public static void main(String[] args) throws Exception {
141        if (!System.getProperty("os.name").startsWith("Windows"))
142            return;
143
144        if (args.length == 0) {
145            start();
146        } else {
147            if (args[0].equals("-child")) {
148                child(Integer.parseInt(args[1]));
149            }
150        }
151    }
152}
153