StreamsSurviveDestroy.java revision 6073:cea72c2bf071
1/*
2 * Copyright (c) 2003, 2011, 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 4820217
26 * @summary Ensure that pending reads on stdout and stderr streams
27 *          return -1 when the process is destroyed
28 */
29
30import java.io.*;
31import java.util.concurrent.*;
32
33
34public class StreamsSurviveDestroy {
35
36    private static class Copier extends Thread {
37
38        String name;
39        InputStream in;
40        OutputStream out;
41        boolean wantInterrupt;
42        boolean acceptException;
43        Exception exc = null;
44        CountDownLatch latch;
45
46        Copier(String name, InputStream in, OutputStream out,
47               boolean ae, boolean wi, CountDownLatch l)
48        {
49            this.name = name;
50            this.in = in;
51            this.out = out;
52            this.acceptException = ae;
53            this.wantInterrupt = wi;
54            this.latch = l;
55            setName(name);
56            start();
57        }
58
59        private void log(String s) {
60            System.err.println("  " + name + ": " + s);
61        }
62
63        public void run() {
64            byte[] buf = new byte[4242];
65            latch.countDown();
66            for (;;) {
67                try {
68                    int n = in.read(buf);
69                    if (n < 0) {
70                        System.err.println("  EOF");
71                        break;
72                    }
73                    out.write(buf, 0, n);
74                } catch (IOException x) {
75                    if (wantInterrupt) {
76                        if (x instanceof InterruptedIOException) {
77                            log("Interrupted as expected");
78                            return;
79                        }
80                        exc = new Exception(name
81                                            + ": Not interrupted as expected");
82                        return;
83                    }
84                    exc = x;
85                    if (acceptException) {
86                        log("Thrown, but okay: " + x);
87                        return;
88                    }
89                    return;
90                }
91            }
92        }
93
94        public void check() throws Exception {
95            if (!acceptException && exc != null)
96                throw new Exception(name + ": Exception thrown", exc);
97        }
98
99    }
100
101    static void test() throws Exception {
102        CountDownLatch latch = new CountDownLatch(2);
103
104        System.err.println("test");
105        Process p = Runtime.getRuntime().exec("/bin/cat");
106        Copier cp1 = new Copier("out", p.getInputStream(), System.err,
107                                false, false, latch);
108        Copier cp2 = new Copier("err", p.getErrorStream(), System.err,
109                                false, false, latch);
110        latch.await();    // Wait till both Copiers about to read
111        Thread.sleep(100);// Give both Copiers a chance to start read
112
113        p.destroy();
114        System.err.println("  exit: " + p.waitFor());
115        cp1.join();
116        cp1.check();
117        cp2.join();
118        cp2.check();
119    }
120
121    static void testCloseBeforeDestroy() throws Exception {
122        CountDownLatch latch = new CountDownLatch(2);
123
124        System.err.println("testCloseBeforeDestroy");
125        Process p = Runtime.getRuntime().exec("/bin/cat");
126        Copier cp1 = new Copier("out", p.getInputStream(), System.err,
127                                true, false, latch);
128        Copier cp2 = new Copier("err", p.getErrorStream(), System.err,
129                                true, false, latch);
130        latch.await();    // Wait till both Copiers about to read
131        Thread.sleep(100);// Give both Copiers a chance to start read
132
133        p.getInputStream().close();
134        p.getErrorStream().close();
135        p.destroy();
136        System.err.println("  exit: " + p.waitFor());
137        cp1.join();
138        cp1.check();
139        cp2.join();
140        cp2.check();
141    }
142
143    static void testCloseAfterDestroy() throws Exception {
144        CountDownLatch latch = new CountDownLatch(2);
145        System.err.println("testCloseAfterDestroy");
146        Process p = Runtime.getRuntime().exec("/bin/cat");
147        Copier cp1 = new Copier("out", p.getInputStream(), System.err,
148                                true, false,latch);
149        Copier cp2 = new Copier("err", p.getErrorStream(), System.err,
150                                true, false, latch);
151
152        latch.await();    // Wait till both Copiers about to read
153        Thread.sleep(100);// Give both Copiers a chance to start read
154
155        p.destroy();
156        p.getInputStream().close();
157        p.getErrorStream().close();
158        System.err.println("  exit: " + p.waitFor());
159        cp1.join();
160        cp1.check();
161        cp2.join();
162        cp2.check();
163    }
164
165    static void testInterrupt() throws Exception {
166        CountDownLatch latch = new CountDownLatch(2);
167        System.err.println("testInterrupt");
168        Process p = Runtime.getRuntime().exec("/bin/cat");
169        Copier cp1 = new Copier("out", p.getInputStream(), System.err,
170                                false, true, latch);
171        Copier cp2 = new Copier("err", p.getErrorStream(), System.err,
172                                false, true, latch);
173        latch.await();    // Wait till both Copiers about to read
174        Thread.sleep(100);// Give both Copiers a chance to start read
175
176        cp1.interrupt();
177        cp2.interrupt();
178        Thread.sleep(100);
179        p.destroy();
180        System.err.println("  exit: " + p.waitFor());
181        cp1.join();
182        cp1.check();
183        cp2.join();
184        cp2.check();
185    }
186
187    public static void main(String[] args) throws Exception {
188
189        // Applies only to Solaris; Linux and Windows
190        // behave a little differently
191        if (!System.getProperty("os.name").equals("SunOS"))
192            return;
193
194        test();
195        testCloseBeforeDestroy();
196        testCloseAfterDestroy();
197        testInterrupt();
198    }
199}
200