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.BufferedInputStream;
29 import java.io.BufferedOutputStream;
30 import java.io.ByteArrayInputStream;
31 import java.io.FileDescriptor;
32 import java.io.FileInputStream;
33 import java.io.FileOutputStream;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.io.OutputStream;
37 import java.util.Arrays;
38 import java.util.concurrent.Executors;
39 import java.util.concurrent.Executor;
40 import java.util.concurrent.ThreadFactory;
41 import java.security.AccessController;
42 import static java.security.AccessController.doPrivileged;
43 import java.security.PrivilegedAction;
44 import java.security.PrivilegedActionException;
45 import java.security.PrivilegedExceptionAction;
46
47 /**
48 * java.lang.Process subclass in the UNIX environment.
49 *
50 * @author Mario Wolczko and Ross Knippel.
51 * @author Konstantin Kladko (ported to Bsd)
52 * @author Martin Buchholz
53 */
54 final class UNIXProcess extends Process {
55 private static final sun.misc.JavaIOFileDescriptorAccess fdAccess
56 = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess();
57
58 private final int pid;
59 private int exitcode;
60 private boolean hasExited;
195
196 public OutputStream getOutputStream() {
197 return stdin;
198 }
199
200 public InputStream getInputStream() {
201 return stdout;
202 }
203
204 public InputStream getErrorStream() {
205 return stderr;
206 }
207
208 public synchronized int waitFor() throws InterruptedException {
209 while (!hasExited) {
210 wait();
211 }
212 return exitcode;
213 }
214
215 public synchronized int exitValue() {
216 if (!hasExited) {
217 throw new IllegalThreadStateException("process hasn't exited");
218 }
219 return exitcode;
220 }
221
222 private static native void destroyProcess(int pid);
223 public void destroy() {
224 // There is a risk that pid will be recycled, causing us to
225 // kill the wrong process! So we only terminate processes
226 // that appear to still be running. Even with this check,
227 // there is an unavoidable race condition here, but the window
228 // is very small, and OSes try hard to not recycle pids too
229 // soon, so this is quite safe.
230 synchronized (this) {
231 if (!hasExited)
232 destroyProcess(pid);
233 }
234 try { stdin.close(); } catch (IOException ignored) {}
235 try { stdout.close(); } catch (IOException ignored) {}
236 try { stderr.close(); } catch (IOException ignored) {}
237 }
238
239 /* This routine initializes JNI field offsets for the class */
240 private static native void initIDs();
241
242 static {
243 initIDs();
244 }
245
246 /**
247 * A buffered input stream for a subprocess pipe file descriptor
248 * that allows the underlying file descriptor to be reclaimed when
249 * the process exits, via the processExited hook.
250 *
251 * This is tricky because we do not want the user-level InputStream to be
252 * closed until the user invokes close(), and we need to continue to be
253 * able to read any buffered data lingering in the OS pipe buffer.
254 */
255 static class ProcessPipeInputStream extends BufferedInputStream {
256 ProcessPipeInputStream(int fd) {
257 super(new FileInputStream(newFileDescriptor(fd)));
258 }
|
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.BufferedInputStream;
29 import java.io.BufferedOutputStream;
30 import java.io.ByteArrayInputStream;
31 import java.io.FileDescriptor;
32 import java.io.FileInputStream;
33 import java.io.FileOutputStream;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.io.OutputStream;
37 import java.util.Arrays;
38 import java.util.concurrent.Executors;
39 import java.util.concurrent.Executor;
40 import java.util.concurrent.ThreadFactory;
41 import java.util.concurrent.TimeUnit;
42 import java.security.AccessController;
43 import static java.security.AccessController.doPrivileged;
44 import java.security.PrivilegedAction;
45 import java.security.PrivilegedActionException;
46 import java.security.PrivilegedExceptionAction;
47
48 /**
49 * java.lang.Process subclass in the UNIX environment.
50 *
51 * @author Mario Wolczko and Ross Knippel.
52 * @author Konstantin Kladko (ported to Bsd)
53 * @author Martin Buchholz
54 */
55 final class UNIXProcess extends Process {
56 private static final sun.misc.JavaIOFileDescriptorAccess fdAccess
57 = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess();
58
59 private final int pid;
60 private int exitcode;
61 private boolean hasExited;
196
197 public OutputStream getOutputStream() {
198 return stdin;
199 }
200
201 public InputStream getInputStream() {
202 return stdout;
203 }
204
205 public InputStream getErrorStream() {
206 return stderr;
207 }
208
209 public synchronized int waitFor() throws InterruptedException {
210 while (!hasExited) {
211 wait();
212 }
213 return exitcode;
214 }
215
216 @Override
217 public synchronized boolean waitFor(long timeout, TimeUnit unit)
218 throws InterruptedException
219 {
220 if (hasExited) return true;
221 if (timeout <= 0) return false;
222
223 long timeoutAsNanos = unit.toNanos(timeout);
224 long startTime = System.nanoTime();
225 long rem = timeoutAsNanos;
226
227 while (!hasExited && (rem > 0)) {
228 wait(Math.max(TimeUnit.NANOSECONDS.toMillis(rem), 1));
229 rem = timeoutAsNanos - (System.nanoTime() - startTime);
230 }
231 return hasExited;
232 }
233
234 public synchronized int exitValue() {
235 if (!hasExited) {
236 throw new IllegalThreadStateException("process hasn't exited");
237 }
238 return exitcode;
239 }
240
241 private static native void destroyProcess(int pid, boolean force);
242 private void destroy(boolean force) {
243 // There is a risk that pid will be recycled, causing us to
244 // kill the wrong process! So we only terminate processes
245 // that appear to still be running. Even with this check,
246 // there is an unavoidable race condition here, but the window
247 // is very small, and OSes try hard to not recycle pids too
248 // soon, so this is quite safe.
249 synchronized (this) {
250 if (!hasExited)
251 destroyProcess(pid, force);
252 }
253 try { stdin.close(); } catch (IOException ignored) {}
254 try { stdout.close(); } catch (IOException ignored) {}
255 try { stderr.close(); } catch (IOException ignored) {}
256 }
257
258 public void destroy() {
259 destroy(false);
260 }
261
262 @Override
263 public Process destroyForcibly() {
264 destroy(true);
265 return this;
266 }
267
268 @Override
269 public synchronized boolean isAlive() {
270 return !hasExited;
271 }
272
273 /* This routine initializes JNI field offsets for the class */
274 private static native void initIDs();
275
276 static {
277 initIDs();
278 }
279
280 /**
281 * A buffered input stream for a subprocess pipe file descriptor
282 * that allows the underlying file descriptor to be reclaimed when
283 * the process exits, via the processExited hook.
284 *
285 * This is tricky because we do not want the user-level InputStream to be
286 * closed until the user invokes close(), and we need to continue to be
287 * able to read any buffered data lingering in the OS pipe buffer.
288 */
289 static class ProcessPipeInputStream extends BufferedInputStream {
290 ProcessPipeInputStream(int fd) {
291 super(new FileInputStream(newFileDescriptor(fd)));
292 }
|