/* * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* @test * @bug 4820217 * @summary Ensure that pending reads on stdout and stderr streams * return -1 when the process is destroyed */ import java.io.*; import java.util.concurrent.*; public class StreamsSurviveDestroy { private static class Copier extends Thread { String name; InputStream in; OutputStream out; boolean wantInterrupt; boolean acceptException; Exception exc = null; CountDownLatch latch; Copier(String name, InputStream in, OutputStream out, boolean ae, boolean wi, CountDownLatch l) { this.name = name; this.in = in; this.out = out; this.acceptException = ae; this.wantInterrupt = wi; this.latch = l; setName(name); start(); } private void log(String s) { System.err.println(" " + name + ": " + s); } public void run() { byte[] buf = new byte[4242]; latch.countDown(); for (;;) { try { int n = in.read(buf); if (n < 0) { System.err.println(" EOF"); break; } out.write(buf, 0, n); } catch (IOException x) { if (wantInterrupt) { if (x instanceof InterruptedIOException) { log("Interrupted as expected"); return; } exc = new Exception(name + ": Not interrupted as expected"); return; } exc = x; if (acceptException) { log("Thrown, but okay: " + x); return; } return; } } } public void check() throws Exception { if (!acceptException && exc != null) throw new Exception(name + ": Exception thrown", exc); } } static void test() throws Exception { CountDownLatch latch = new CountDownLatch(2); System.err.println("test"); Process p = Runtime.getRuntime().exec("/bin/cat"); Copier cp1 = new Copier("out", p.getInputStream(), System.err, false, false, latch); Copier cp2 = new Copier("err", p.getErrorStream(), System.err, false, false, latch); latch.await(); // Wait till both Copiers about to read Thread.sleep(100);// Give both Copiers a chance to start read p.destroy(); System.err.println(" exit: " + p.waitFor()); cp1.join(); cp1.check(); cp2.join(); cp2.check(); } static void testCloseBeforeDestroy() throws Exception { CountDownLatch latch = new CountDownLatch(2); System.err.println("testCloseBeforeDestroy"); Process p = Runtime.getRuntime().exec("/bin/cat"); Copier cp1 = new Copier("out", p.getInputStream(), System.err, true, false, latch); Copier cp2 = new Copier("err", p.getErrorStream(), System.err, true, false, latch); latch.await(); // Wait till both Copiers about to read Thread.sleep(100);// Give both Copiers a chance to start read p.getInputStream().close(); p.getErrorStream().close(); p.destroy(); System.err.println(" exit: " + p.waitFor()); cp1.join(); cp1.check(); cp2.join(); cp2.check(); } static void testCloseAfterDestroy() throws Exception { CountDownLatch latch = new CountDownLatch(2); System.err.println("testCloseAfterDestroy"); Process p = Runtime.getRuntime().exec("/bin/cat"); Copier cp1 = new Copier("out", p.getInputStream(), System.err, true, false,latch); Copier cp2 = new Copier("err", p.getErrorStream(), System.err, true, false, latch); latch.await(); // Wait till both Copiers about to read Thread.sleep(100);// Give both Copiers a chance to start read p.destroy(); p.getInputStream().close(); p.getErrorStream().close(); System.err.println(" exit: " + p.waitFor()); cp1.join(); cp1.check(); cp2.join(); cp2.check(); } static void testInterrupt() throws Exception { CountDownLatch latch = new CountDownLatch(2); System.err.println("testInterrupt"); Process p = Runtime.getRuntime().exec("/bin/cat"); Copier cp1 = new Copier("out", p.getInputStream(), System.err, false, true, latch); Copier cp2 = new Copier("err", p.getErrorStream(), System.err, false, true, latch); latch.await(); // Wait till both Copiers about to read Thread.sleep(100);// Give both Copiers a chance to start read cp1.interrupt(); cp2.interrupt(); Thread.sleep(100); p.destroy(); System.err.println(" exit: " + p.waitFor()); cp1.join(); cp1.check(); cp2.join(); cp2.check(); } public static void main(String[] args) throws Exception { // Applies only to Solaris; Linux and Windows // behave a little differently if (!System.getProperty("os.name").equals("SunOS")) return; test(); testCloseBeforeDestroy(); testCloseAfterDestroy(); testInterrupt(); } }