< prev index next >
src/java.base/unix/classes/java/lang/ProcessImpl.java
Print this page
*** 23,53 ****
* questions.
*/
package java.lang;
! import java.lang.ProcessBuilder.Redirect;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
! import java.security.AccessController;
import static java.security.AccessController.doPrivileged;
- import java.security.PrivilegedAction;
- import java.security.PrivilegedActionException;
- import java.security.PrivilegedExceptionAction;
/**
* java.lang.Process subclass in the UNIX environment.
*
* @author Mario Wolczko and Ross Knippel.
--- 23,58 ----
* questions.
*/
package java.lang;
! import sun.nio.ch.SelChImpl;
!
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
+ import java.io.Closeable;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+ import java.lang.ProcessBuilder.Redirect;
+ import java.nio.channels.Pipe;
+ import java.security.AccessController;
+ import java.security.PrivilegedAction;
+ import java.security.PrivilegedActionException;
+ import java.security.PrivilegedExceptionAction;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
!
import static java.security.AccessController.doPrivileged;
/**
* java.lang.Process subclass in the UNIX environment.
*
* @author Mario Wolczko and Ross Knippel.
*** 73,82 ****
--- 78,91 ----
private /* final */ InputStream stderr;
// only used on Solaris
private /* final */ DeferredCloseInputStream stdout_inner_stream;
+ private final Pipe.SinkChannel stdinChannel;
+ private final Pipe.SourceChannel stdoutChannel;
+ private final Pipe.SourceChannel stderrChannel;
+
private static enum LaunchMechanism {
// order IS important!
FORK,
POSIX_SPAWN,
VFORK
*** 219,258 ****
FileInputStream f0 = null;
FileOutputStream f1 = null;
FileOutputStream f2 = null;
try {
if (redirects == null) {
std_fds = new int[] { -1, -1, -1 };
} else {
std_fds = new int[3];
! if (redirects[0] == Redirect.PIPE)
std_fds[0] = -1;
! else if (redirects[0] == Redirect.INHERIT)
std_fds[0] = 0;
! else {
f0 = new FileInputStream(redirects[0].file());
std_fds[0] = fdAccess.get(f0.getFD());
}
! if (redirects[1] == Redirect.PIPE)
std_fds[1] = -1;
! else if (redirects[1] == Redirect.INHERIT)
std_fds[1] = 1;
! else {
f1 = new FileOutputStream(redirects[1].file(),
redirects[1].append());
std_fds[1] = fdAccess.get(f1.getFD());
}
! if (redirects[2] == Redirect.PIPE)
std_fds[2] = -1;
! else if (redirects[2] == Redirect.INHERIT)
std_fds[2] = 2;
! else {
f2 = new FileOutputStream(redirects[2].file(),
redirects[2].append());
std_fds[2] = fdAccess.get(f2.getFD());
}
}
--- 228,293 ----
FileInputStream f0 = null;
FileOutputStream f1 = null;
FileOutputStream f2 = null;
+ Pipe p0 = null;
+ Pipe p1 = null;
+ Pipe p2 = null;
+
try {
if (redirects == null) {
std_fds = new int[] { -1, -1, -1 };
} else {
std_fds = new int[3];
! if (redirects[0] == Redirect.PIPE) {
std_fds[0] = -1;
! } else if (redirects[0] == Redirect.PIPE_CHANNEL) {
! p0 = Pipe.open();
! if (!(p0.source() instanceof SelChImpl)) {
! throw new UnsupportedOperationException("Unsupported SelectorProvider");
! }
! std_fds[0] = ((SelChImpl) p0.source()).getFDVal();
! } else if (redirects[0] == Redirect.INHERIT) {
std_fds[0] = 0;
! } else {
f0 = new FileInputStream(redirects[0].file());
std_fds[0] = fdAccess.get(f0.getFD());
}
! if (redirects[1] == Redirect.PIPE) {
std_fds[1] = -1;
! } else if (redirects[1] == Redirect.PIPE_CHANNEL) {
! p1 = Pipe.open();
! if (!(p1.sink() instanceof SelChImpl)) {
! throw new UnsupportedOperationException("Unsupported SelectorProvider");
! }
! std_fds[1] = ((SelChImpl) p1.sink()).getFDVal();
! } else if (redirects[1] == Redirect.INHERIT) {
std_fds[1] = 1;
! } else {
f1 = new FileOutputStream(redirects[1].file(),
redirects[1].append());
std_fds[1] = fdAccess.get(f1.getFD());
}
! if (redirects[2] == Redirect.PIPE) {
std_fds[2] = -1;
! } else if (redirects[2] == Redirect.PIPE_CHANNEL) {
! if (redirectErrorStream) {
! std_fds[2] = -1;
! } else {
! p2 = Pipe.open();
! if (!(p2.sink() instanceof SelChImpl)) {
! throw new UnsupportedOperationException("Unsupported SelectorProvider");
! }
! std_fds[2] = ((SelChImpl) p2.sink()).getFDVal();
! }
! } else if (redirects[2] == Redirect.INHERIT) {
std_fds[2] = 2;
! } else {
f2 = new FileOutputStream(redirects[2].file(),
redirects[2].append());
std_fds[2] = fdAccess.get(f2.getFD());
}
}
*** 261,280 ****
(toCString(cmdarray[0]),
argBlock, args.length,
envBlock, envc[0],
toCString(dir),
std_fds,
redirectErrorStream);
} finally {
! // In theory, close() can throw IOException
! // (although it is rather unlikely to happen here)
! try { if (f0 != null) f0.close(); }
! finally {
! try { if (f1 != null) f1.close(); }
! finally { if (f2 != null) f2.close(); }
}
}
}
/**
* Creates a process. Depending on the {@code mode} flag, this is done by
--- 296,335 ----
(toCString(cmdarray[0]),
argBlock, args.length,
envBlock, envc[0],
toCString(dir),
std_fds,
+ new Pipe[] { p0, p1, p2 },
redirectErrorStream);
+ } catch (Exception e) {
+ // close unused pipe ends
+ if (p0 != null) close(p0.sink());
+ if (p1 != null) close(p1.source());
+ if (p2 != null) close(p2.source());
+ // re-throw
+ throw e;
} finally {
! // close dup-ed file handles
! close(f0);
! close(f1);
! close(f2);
! // close dup-ed pipe ends
! if (p0 != null) close(p0.source());
! if (p1 != null) close(p1.sink());
! if (p2 != null) close(p2.sink());
}
}
+
+ private static IOException close(Closeable closeable) {
+ if (closeable != null) {
+ try {
+ closeable.close();
+ } catch (IOException e) {
+ return e;
+ }
+ }
+ return null;
}
/**
* Creates a process. Depending on the {@code mode} flag, this is done by
*** 307,316 ****
--- 362,372 ----
private ProcessImpl(final byte[] prog,
final byte[] argBlock, final int argc,
final byte[] envBlock, final int envc,
final byte[] dir,
final int[] fds,
+ final Pipe[] pipes,
final boolean redirectErrorStream)
throws IOException {
pid = forkAndExec(launchMechanism.ordinal() + 1,
helperpath,
*** 328,337 ****
--- 384,397 ----
return null;
});
} catch (PrivilegedActionException ex) {
throw (IOException) ex.getException();
}
+
+ stdinChannel = (pipes[0] == null) ? null : pipes[0].sink();
+ stdoutChannel = (pipes[1] == null) ? null : pipes[1].source();
+ stderrChannel = (pipes[2] == null) ? null : pipes[2].source();
}
static FileDescriptor newFileDescriptor(int fd) {
FileDescriptor fileDescriptor = new FileDescriptor();
fdAccess.set(fileDescriptor, fd);
*** 456,465 ****
--- 516,537 ----
public InputStream getErrorStream() {
return stderr;
}
+ public Pipe.SinkChannel getOutputChannel() {
+ return stdinChannel;
+ }
+
+ public Pipe.SourceChannel getInputChannel() {
+ return stdoutChannel;
+ }
+
+ public Pipe.SourceChannel getErrorChannel() {
+ return stderrChannel;
+ }
+
public synchronized int waitFor() throws InterruptedException {
while (!hasExited) {
wait();
}
return exitcode;
< prev index next >