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 if (hasExited) return true;
220 if (timeout <= 0) return false;
221
222 long now = System.nanoTime();
223 long end = now + TimeUnit.NANOSECONDS.convert(timeout, unit);
224 if (end <= 0) // overflow
225 end = Long.MAX_VALUE;
226
227 long rem = end - now;
228 while (!hasExited && (rem > 0)) {
229 wait(TimeUnit.NANOSECONDS.toMillis(rem));
230 rem = end - System.nanoTime();
231 }
232 return hasExited;
233 }
234
235 public synchronized int exitValue() {
236 if (!hasExited) {
237 throw new IllegalThreadStateException("process hasn't exited");
238 }
239 return exitcode;
240 }
241
242 private static native void destroyProcess(int pid, boolean force);
243 private void destroy(boolean force) {
244 // There is a risk that pid will be recycled, causing us to
245 // kill the wrong process! So we only terminate processes
246 // that appear to still be running. Even with this check,
247 // there is an unavoidable race condition here, but the window
248 // is very small, and OSes try hard to not recycle pids too
249 // soon, so this is quite safe.
250 synchronized (this) {
251 if (!hasExited)
252 destroyProcess(pid, force);
253 }
254 try { stdin.close(); } catch (IOException ignored) {}
255 try { stdout.close(); } catch (IOException ignored) {}
256 try { stderr.close(); } catch (IOException ignored) {}
257 }
258
259 public void destroy() {
260 destroy(false);
261 }
262
263 @Override
264 public Process destroyForcibly() {
265 destroy(true);
266 return this;
267 }
268
269 @Override
270 public synchronized boolean isAlive() {
271 return !hasExited;
272 }
273
274 /* This routine initializes JNI field offsets for the class */
275 private static native void initIDs();
276
277 static {
278 initIDs();
279 }
280
281 /**
282 * A buffered input stream for a subprocess pipe file descriptor
283 * that allows the underlying file descriptor to be reclaimed when
284 * the process exits, via the processExited hook.
285 *
286 * This is tricky because we do not want the user-level InputStream to be
287 * closed until the user invokes close(), and we need to continue to be
288 * able to read any buffered data lingering in the OS pipe buffer.
289 */
290 static class ProcessPipeInputStream extends BufferedInputStream {
291 ProcessPipeInputStream(int fd) {
292 super(new FileInputStream(newFileDescriptor(fd)));
293 }
|