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 if (hasExited) return true;
166 if (timeout <= 0) return false;
167
168 long now = System.nanoTime();
169 long end = now + TimeUnit.NANOSECONDS.convert(timeout, unit);
170 if (end <= 0) // overflow
171 end = Long.MAX_VALUE;
172
173 long rem = end - now;
174 while (!hasExited && (rem > 0)) {
175 wait(TimeUnit.NANOSECONDS.toMillis(rem));
176 rem = end - System.nanoTime();
177 }
178 return hasExited;
179 }
180
181 public synchronized int exitValue() {
182 if (!hasExited) {
183 throw new IllegalThreadStateException("process hasn't exited");
184 }
185 return exitcode;
186 }
187
188 private static native void destroyProcess(int pid, boolean force);
189 private synchronized void destroy(boolean force) {
190 // There is a risk that pid will be recycled, causing us to
191 // kill the wrong process! So we only terminate processes
192 // that appear to still be running. Even with this check,
193 // there is an unavoidable race condition here, but the window
194 // is very small, and OSes try hard to not recycle pids too
195 // soon, so this is quite safe.
196 if (!hasExited)
197 destroyProcess(pid, force);
198 try {
199 stdin_stream.close();
200 if (stdout_inner_stream != null)
201 stdout_inner_stream.closeDeferred(stdout_stream);
202 if (stderr_stream instanceof DeferredCloseInputStream)
203 ((DeferredCloseInputStream) stderr_stream)
204 .closeDeferred(stderr_stream);
205 } catch (IOException e) {
206 // ignore
207 }
208 }
209
210 public void destroy() {
211 destroy(false);
212 }
213
214 @Override
215 public Process destroyForcibly() {
216 destroy(true);
217 return this;
218 }
219
220 @Override
221 public synchronized boolean isAlive() {
222 return !hasExited;
223 }
224
225 // A FileInputStream that supports the deferment of the actual close
226 // operation until the last pending I/O operation on the stream has
227 // finished. This is required on Solaris because we must close the stdin
228 // and stdout streams in the destroy method in order to reclaim the
229 // underlying file descriptors. Doing so, however, causes any thread
230 // currently blocked in a read on one of those streams to receive an
231 // IOException("Bad file number"), which is incompatible with historical
232 // behavior. By deferring the close we allow any pending reads to see -1
233 // (EOF) as they did before.
234 //
235 private static class DeferredCloseInputStream
236 extends FileInputStream
237 {
238
239 private DeferredCloseInputStream(FileDescriptor fd) {
240 super(fd);
241 }
242
243 private Object lock = new Object(); // For the following fields
244 private boolean closePending = false;
|