1 /*
2 * Copyright (c) 1995, 2010, 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang;
27
28 import java.io.*;
29
30 /* java.lang.Process subclass in the UNIX environment.
31 *
32 * @author Mario Wolczko and Ross Knippel.
33 */
34
35 final class UNIXProcess extends Process {
36 private static final sun.misc.JavaIOFileDescriptorAccess fdAccess
37 = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess();
38
39 private final int pid;
40 private int exitcode;
41 private boolean hasExited;
42
43 private OutputStream stdin_stream;
44 private InputStream stdout_stream;
45 private DeferredCloseInputStream stdout_inner_stream;
46 private InputStream stderr_stream;
47
48 /* this is for the reaping thread */
141
142 public OutputStream getOutputStream() {
143 return stdin_stream;
144 }
145
146 public InputStream getInputStream() {
147 return stdout_stream;
148 }
149
150 public InputStream getErrorStream() {
151 return stderr_stream;
152 }
153
154 public synchronized int waitFor() throws InterruptedException {
155 while (!hasExited) {
156 wait();
157 }
158 return exitcode;
159 }
160
161 public synchronized int exitValue() {
162 if (!hasExited) {
163 throw new IllegalThreadStateException("process hasn't exited");
164 }
165 return exitcode;
166 }
167
168 private static native void destroyProcess(int pid);
169 public synchronized void destroy() {
170 // There is a risk that pid will be recycled, causing us to
171 // kill the wrong process! So we only terminate processes
172 // that appear to still be running. Even with this check,
173 // there is an unavoidable race condition here, but the window
174 // is very small, and OSes try hard to not recycle pids too
175 // soon, so this is quite safe.
176 if (!hasExited)
177 destroyProcess(pid);
178 try {
179 stdin_stream.close();
180 if (stdout_inner_stream != null)
181 stdout_inner_stream.closeDeferred(stdout_stream);
182 if (stderr_stream instanceof DeferredCloseInputStream)
183 ((DeferredCloseInputStream) stderr_stream)
184 .closeDeferred(stderr_stream);
185 } catch (IOException e) {
186 // ignore
187 }
188 }
189
190 // A FileInputStream that supports the deferment of the actual close
191 // operation until the last pending I/O operation on the stream has
192 // finished. This is required on Solaris because we must close the stdin
193 // and stdout streams in the destroy method in order to reclaim the
194 // underlying file descriptors. Doing so, however, causes any thread
195 // currently blocked in a read on one of those streams to receive an
196 // IOException("Bad file number"), which is incompatible with historical
197 // behavior. By deferring the close we allow any pending reads to see -1
198 // (EOF) as they did before.
199 //
200 private static class DeferredCloseInputStream
201 extends FileInputStream
202 {
203
204 private DeferredCloseInputStream(FileDescriptor fd) {
205 super(fd);
206 }
207
208 private Object lock = new Object(); // For the following fields
209 private boolean closePending = false;
|
1 /*
2 * Copyright (c) 1995, 2012, 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang;
27
28 import java.io.*;
29 import java.util.concurrent.TimeUnit;
30
31 /* java.lang.Process subclass in the UNIX environment.
32 *
33 * @author Mario Wolczko and Ross Knippel.
34 */
35
36 final class UNIXProcess extends Process {
37 private static final sun.misc.JavaIOFileDescriptorAccess fdAccess
38 = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess();
39
40 private final int pid;
41 private int exitcode;
42 private boolean hasExited;
43
44 private OutputStream stdin_stream;
45 private InputStream stdout_stream;
46 private DeferredCloseInputStream stdout_inner_stream;
47 private InputStream stderr_stream;
48
49 /* this is for the reaping thread */
142
143 public OutputStream getOutputStream() {
144 return stdin_stream;
145 }
146
147 public InputStream getInputStream() {
148 return stdout_stream;
149 }
150
151 public InputStream getErrorStream() {
152 return stderr_stream;
153 }
154
155 public synchronized int waitFor() throws InterruptedException {
156 while (!hasExited) {
157 wait();
158 }
159 return exitcode;
160 }
161
162 @Override
163 public synchronized boolean waitFor(long timeout, TimeUnit unit)
164 throws InterruptedException
165 {
166 if (hasExited) return true;
167 if (timeout <= 0) return false;
168
169 long timeoutAsNanos = unit.toNanos(timeout);
170 long startTime = System.nanoTime();
171 long rem = timeoutAsNanos;
172
173 while (!hasExited && (rem > 0)) {
174 wait(Math.max(TimeUnit.NANOSECONDS.toMillis(rem), 1));
175 rem = timeoutAsNanos - (System.nanoTime() - startTime);
176 }
177 return hasExited;
178 }
179
180 public synchronized int exitValue() {
181 if (!hasExited) {
182 throw new IllegalThreadStateException("process hasn't exited");
183 }
184 return exitcode;
185 }
186
187 private static native void destroyProcess(int pid, boolean force);
188 private synchronized void destroy(boolean force) {
189 // There is a risk that pid will be recycled, causing us to
190 // kill the wrong process! So we only terminate processes
191 // that appear to still be running. Even with this check,
192 // there is an unavoidable race condition here, but the window
193 // is very small, and OSes try hard to not recycle pids too
194 // soon, so this is quite safe.
195 if (!hasExited)
196 destroyProcess(pid, force);
197 try {
198 stdin_stream.close();
199 if (stdout_inner_stream != null)
200 stdout_inner_stream.closeDeferred(stdout_stream);
201 if (stderr_stream instanceof DeferredCloseInputStream)
202 ((DeferredCloseInputStream) stderr_stream)
203 .closeDeferred(stderr_stream);
204 } catch (IOException e) {
205 // ignore
206 }
207 }
208
209 public void destroy() {
210 destroy(false);
211 }
212
213 @Override
214 public Process destroyForcibly() {
215 destroy(true);
216 return this;
217 }
218
219 @Override
220 public synchronized boolean isAlive() {
221 return !hasExited;
222 }
223
224 // A FileInputStream that supports the deferment of the actual close
225 // operation until the last pending I/O operation on the stream has
226 // finished. This is required on Solaris because we must close the stdin
227 // and stdout streams in the destroy method in order to reclaim the
228 // underlying file descriptors. Doing so, however, causes any thread
229 // currently blocked in a read on one of those streams to receive an
230 // IOException("Bad file number"), which is incompatible with historical
231 // behavior. By deferring the close we allow any pending reads to see -1
232 // (EOF) as they did before.
233 //
234 private static class DeferredCloseInputStream
235 extends FileInputStream
236 {
237
238 private DeferredCloseInputStream(FileDescriptor fd) {
239 super(fd);
240 }
241
242 private Object lock = new Object(); // For the following fields
243 private boolean closePending = false;
|