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