blob: a18e60692601a3bdc7b6705adc1b889d39800a1e [file] [log] [blame]
utac0ffe5d2013-08-08 09:16:16 +04001/*
2 * Copyright (c) 2013, 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 * @bug 6921885
27 * @run main/othervm SiblingIOEHandle
28 * @summary inherit IOE handles and MS CreateProcess limitations (kb315939)
29 */
30
31import java.io.BufferedReader;
32import java.io.File;
33import java.io.IOException;
34import java.io.InputStreamReader;
35import java.util.concurrent.BrokenBarrierException;
36import java.util.concurrent.CyclicBarrier;
37
38public class SiblingIOEHandle {
39 private static enum APP {
40 B, C;
41 }
42 private static File stopC = new File(".\\StopCs.txt");
43 private static String SIGNAL = "B child reported.";
44 private static String JAVA_EXE = System.getProperty("java.home")
45 + File.separator + "bin"
46 + File.separator + "java";
47
48 private static String[] getCommandArray(String processName) {
49 String[] cmdArray = {
50 JAVA_EXE,
51 "-cp",
52 System.getProperty("java.class.path"),
53 SiblingIOEHandle.class.getName(),
54 processName
55 };
56 return cmdArray;
57 }
58
59 public static void main(String[] args) {
60 if (!System.getProperty("os.name").startsWith("Windows")) {
61 return;
62 }
63
64 if (args.length > 0) {
65 APP app = APP.valueOf(args[0]);
66 switch (app) {
67 case B:
68 performB();
69 break;
70 case C:
71 performC();
72 break;
73 }
74 return;
75 }
76 performA(true);
77 performA(false);
78 }
79
80 static boolean procClaunched = false;
81
82 private static void waitAbit() {
83 try {
84 Thread.sleep(0);
85 } catch (InterruptedException ex) {
86 // that was long enough
87 }
88 }
89 private static boolean waitBarrier(CyclicBarrier barrier) {
90 while (true) try {
91 barrier.await();
92 return true;
93 } catch (InterruptedException ex) {
94 continue;
95 } catch (BrokenBarrierException ex) {
96 ex.printStackTrace();
97 return false;
98 }
99 }
100
101 private static void performA(boolean fileOut) {
102 try {
103 stopC.delete();
104 ProcessBuilder builderB = new ProcessBuilder(
105 getCommandArray(APP.B.name()));
106
107 File outB = null;
108 if (fileOut) {
109 outB = new File("outB.txt");
110 builderB.redirectOutput(outB);
111 }
112 builderB.redirectErrorStream(true);
113
114 final CyclicBarrier barrier = new CyclicBarrier(2);
115 Thread procCRunner = new Thread(new Runnable() {
116 @Override public void run() {
117 try {
118 if (waitBarrier(barrier)) {
119 waitAbit();
120 // Run process C next to B ASAP to make an attempt
121 // to capture the B-process IOE handles in C process.
122 Runtime.getRuntime().exec(getCommandArray(APP.C.name()));
123 procClaunched = true;
124 }
125 } catch (IOException ex) {
126 ex.printStackTrace();
127 }
128 }
129 });
130 procCRunner.start();
131
132
133 if (!waitBarrier(barrier)) {
134 throw new Error("Catastrophe in process A! Synchronization failed.");
135 }
136 // Run process B first.
137 Process processB = builderB.start();
138
139 while (true) try {
140 procCRunner.join();
141 break;
142 } catch (InterruptedException ex) {
143 continue;
144 }
145
146 if (!procClaunched) {
147 throw new Error("Catastrophe in process A! C was not launched.");
148 }
149
150 processB.getOutputStream().close();
151 processB.getErrorStream().close();
152
153 if (fileOut) {
154 try {
155 processB.waitFor();
156 } catch (InterruptedException ex) {
157 throw new Error("Catastrophe in process B! B hung up.");
158 }
159 System.err.println("Trying to delete [outB.txt].");
160 if (!outB.delete()) {
161 throw new Error("Greedy brother C deadlock! File share.");
162 }
163 System.err.println("Succeeded in delete [outB.txt].");
164 } else {
165 System.err.println("Read stream start.");
166 try (BufferedReader in = new BufferedReader( new InputStreamReader(
167 processB.getInputStream(), "utf-8")))
168 {
169 String result;
170 while ((result = in.readLine()) != null) {
171 if (!SIGNAL.equals(result)) {
172 throw new Error("Catastrophe in process B! Bad output.");
173 }
174 }
175 }
176 System.err.println("Read stream finished.");
177 }
178 // If JDK-6921885 is not fixed that point is unreachable.
179 // Test timeout exception.
180
181 // write signal file to stop C process.
182 stopC.createNewFile();
183 } catch (IOException ex) {
184 throw new Error("Catastrophe in process A!", ex);
185 }
186 }
187
188 private static void performB() {
189 System.out.println(SIGNAL);
190 }
191
192 private static void performC() {
193 // If JDK-7147084 is not fixed the loop is 5min long.
194 for (int i = 0; i < 5*60; ++i) {
195 try {
196 Thread.sleep(1000);
197 // check for sucess
198 if (stopC.exists())
199 break;
200 } catch (InterruptedException ex) {
201 // that is ok. Longer sleep - better effect.
202 }
203 }
204 }
205}