< 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 >