8216134: (process) ProcessBuilder startPipeline does not hide piped streams
authorrriggs
Mon, 07 Jan 2019 09:29:31 -0500
changeset 53158 b01fe6b2502c
parent 53157 3d60a1696e19
child 53159 9339773f2530
8216134: (process) ProcessBuilder startPipeline does not hide piped streams Reviewed-by: lancea, bchristi, sgroeger
src/java.base/windows/classes/java/lang/ProcessImpl.java
test/jdk/java/lang/ProcessBuilder/PipelineTest.java
--- a/src/java.base/windows/classes/java/lang/ProcessImpl.java	Mon Jan 07 04:56:59 2019 -0800
+++ b/src/java.base/windows/classes/java/lang/ProcessImpl.java	Mon Jan 07 09:29:31 2019 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -106,6 +106,7 @@
         FileOutputStream f2 = null;
 
         try {
+            boolean forceNullOutputStream = false;
             long[] stdHandles;
             if (redirects == null) {
                 stdHandles = new long[] { -1L, -1L, -1L };
@@ -129,6 +130,9 @@
                     stdHandles[1] = fdAccess.getHandle(FileDescriptor.out);
                 } else if (redirects[1] instanceof ProcessBuilder.RedirectPipeImpl) {
                     stdHandles[1] = fdAccess.getHandle(((ProcessBuilder.RedirectPipeImpl) redirects[1]).getFd());
+                    // Force getInputStream to return a null stream,
+                    // the handle is directly assigned to the next process.
+                    forceNullOutputStream = true;
                 } else {
                     f1 = newFileOutputStream(redirects[1].file(),
                                              redirects[1].append());
@@ -149,7 +153,7 @@
             }
 
             Process p = new ProcessImpl(cmdarray, envblock, dir,
-                                   stdHandles, redirectErrorStream);
+                                   stdHandles, forceNullOutputStream, redirectErrorStream);
             if (redirects != null) {
                 // Copy the handles's if they are to be redirected to another process
                 if (stdHandles[0] >= 0
@@ -349,6 +353,7 @@
                         final String envblock,
                         final String path,
                         final long[] stdHandles,
+                        boolean forceNullOutputStream,
                         final boolean redirectErrorStream)
         throws IOException
     {
@@ -437,7 +442,7 @@
                     new FileOutputStream(stdin_fd));
             }
 
-            if (stdHandles[1] == -1L)
+            if (stdHandles[1] == -1L || forceNullOutputStream)
                 stdout_stream = ProcessBuilder.NullInputStream.INSTANCE;
             else {
                 FileDescriptor stdout_fd = new FileDescriptor();
--- a/test/jdk/java/lang/ProcessBuilder/PipelineTest.java	Mon Jan 07 04:56:59 2019 -0800
+++ b/test/jdk/java/lang/ProcessBuilder/PipelineTest.java	Mon Jan 07 09:29:31 2019 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,6 +34,8 @@
 
 /*
  * @test PipelineTest
+ * @bug 8211844
+ * @summary Tests for ProcessBuilder.startPipeline
  */
 
 public class PipelineTest {
@@ -170,7 +172,7 @@
     static void verify(String input, String expected, List<ProcessBuilder> builders) throws IOException {
         File infile = new File("test.in");
         File outfile = new File("test.out");
-        setFileContents(infile, expected);
+        setFileContents(infile, input);
         for (int i = 0; i < builders.size(); i++) {
             ProcessBuilder b = builders.get(i);
             if (i == 0) {
@@ -184,8 +186,8 @@
         verifyProcesses(processes);
         waitForAll(processes);
         String result = fileContents(outfile);
-        System.out.printf(" in: %s%nout: %s%n", input, expected);
-        check(result.equals(expected), "result not as expected");
+        check(result.equals(expected),
+                "result not as expected: " + result + ", expected: " + expected);
     }
 
     /**
@@ -219,11 +221,14 @@
     static void verifyProcesses(List<Process> processes) {
         for (int i = 0; i < processes.size(); i++) {
             Process p = processes.get(i);
+
             if (i != 0) {
                 verifyNullStream(p.getOutputStream(), "getOutputStream");
             }
+            if (i <= processes.size() - 1) {
+                verifyNullStream(p.getInputStream(), "getInputStream");
+            }
             if (i == processes.size() - 1) {
-                verifyNullStream(p.getInputStream(), "getInputStream");
                 verifyNullStream(p.getErrorStream(), "getErrorStream");
             }
         }
@@ -232,7 +237,7 @@
     static void verifyNullStream(OutputStream s, String msg) {
         try {
             s.write(0xff);
-            fail("Stream should have been a NullStream" + msg);
+            fail("Stream should have been a NullStream: " + msg);
         } catch (IOException ie) {
             // expected
         }
@@ -241,7 +246,7 @@
     static void verifyNullStream(InputStream s, String msg) {
         try {
             int len = s.read();
-            check(len == -1, "Stream should have been a NullStream" + msg);
+            check(len == -1, "Stream should have been a NullStream: " + msg);
         } catch (IOException ie) {
             // expected
         }
@@ -271,9 +276,12 @@
     //--------------------- Infrastructure ---------------------------
     static volatile int passed = 0, failed = 0;
     static void pass() {passed++;}
-    static void fail() {failed++; Thread.dumpStack();}
-    static void fail(String msg) {System.err.println(msg); fail();}
-    static void unexpected(Throwable t) {failed++; t.printStackTrace();}
+    static void fail() {failed++; new Exception("Stack trace").printStackTrace(System.out);}
+    static void fail(String msg) {
+        System.out.println(msg); failed++;
+        new Exception("Stack trace: " + msg).printStackTrace(System.out);
+    }
+    static void unexpected(Throwable t) {failed++; t.printStackTrace(System.out);}
     static void check(boolean cond) {if (cond) pass(); else fail();}
     static void check(boolean cond, String m) {if (cond) pass(); else fail(m);}
     static void equal(Object x, Object y) {