jdk/test/java/lang/ProcessBuilder/SiblingIOEHandle.java
changeset 21294 545dfa5b947e
parent 19372 e404c834f1cd
equal deleted inserted replaced
21293:56310f56feac 21294:545dfa5b947e
    35 import java.util.concurrent.BrokenBarrierException;
    35 import java.util.concurrent.BrokenBarrierException;
    36 import java.util.concurrent.CyclicBarrier;
    36 import java.util.concurrent.CyclicBarrier;
    37 
    37 
    38 public class SiblingIOEHandle {
    38 public class SiblingIOEHandle {
    39     private static enum APP {
    39     private static enum APP {
    40         B, C;
    40         A, B, C;
    41     }
    41     }
       
    42 
    42     private static File stopC = new File(".\\StopCs.txt");
    43     private static File stopC = new File(".\\StopCs.txt");
    43     private static String SIGNAL = "B child reported.";
    44     private static String SIGNAL = "B child reported.";
    44     private static String JAVA_EXE = System.getProperty("java.home")
    45     private static String JAVA_EXE = System.getProperty("java.home")
    45         + File.separator + "bin"
    46             + File.separator + "bin"
    46         + File.separator + "java";
    47             + File.separator + "java";
    47 
    48 
    48     private static String[] getCommandArray(String processName) {
    49     private static String[] getCommandArray(String processName) {
    49         String[] cmdArray = {
    50         String[] cmdArray = {
    50             JAVA_EXE,
    51                 JAVA_EXE,
    51             "-cp",
    52                 "-cp",
    52             System.getProperty("java.class.path"),
    53                 System.getProperty("java.class.path"),
    53             SiblingIOEHandle.class.getName(),
    54                 SiblingIOEHandle.class.getName(),
    54             processName
    55                 processName
    55         };
    56         };
    56         return cmdArray;
    57         return cmdArray;
    57     }
    58     }
    58 
    59 
    59     public static void main(String[] args) {
    60     public static void main(String[] args) {
    60         if (!System.getProperty("os.name").startsWith("Windows")) {
    61         if (!System.getProperty("os.name").startsWith("Windows")) {
    61             return;
    62             return;
    62         }
    63         }
    63 
    64 
    64         if (args.length > 0) {
    65         APP app = (args.length > 0) ? APP.valueOf(args[0]) : APP.A;
    65             APP app = APP.valueOf(args[0]);
    66         switch (app) {
    66             switch (app) {
    67             case A:
       
    68                 performA(true);
       
    69                 performA(false);
       
    70                 break;
    67             case B:
    71             case B:
    68                 performB();
    72                 performB();
    69                 break;
    73                 break;
    70             case C:
    74             case C:
    71                 performC();
    75                 performC();
    72                 break;
    76                 break;
    73             }
    77         }
    74             return;
       
    75         }
       
    76         performA(true);
       
    77         performA(false);
       
    78     }
    78     }
    79 
    79 
    80     static boolean procClaunched = false;
    80     static boolean procClaunched = false;
    81 
    81 
    82     private static void waitAbit() {
    82     private static void waitAbit() {
    84             Thread.sleep(0);
    84             Thread.sleep(0);
    85         } catch (InterruptedException ex) {
    85         } catch (InterruptedException ex) {
    86             // that was long enough
    86             // that was long enough
    87         }
    87         }
    88     }
    88     }
       
    89 
    89     private static boolean waitBarrier(CyclicBarrier barrier) {
    90     private static boolean waitBarrier(CyclicBarrier barrier) {
    90         while (true) try {
    91         while (true) try {
    91             barrier.await();
    92             barrier.await();
    92             return true;
    93             return true;
    93         } catch (InterruptedException ex) {
    94         } catch (InterruptedException ex) {
    96             ex.printStackTrace();
    97             ex.printStackTrace();
    97             return false;
    98             return false;
    98         }
    99         }
    99     }
   100     }
   100 
   101 
       
   102     private static class ProcessC implements Runnable {
       
   103         private CyclicBarrier barrier;
       
   104         private Process processC;
       
   105 
       
   106         public ProcessC(CyclicBarrier barrier) {
       
   107             this.barrier = barrier;
       
   108         }
       
   109 
       
   110         @Override
       
   111         public void run() {
       
   112             try {
       
   113                 if (waitBarrier(barrier)) {
       
   114                     waitAbit();
       
   115                     // Run process C next to B ASAP to make an attempt
       
   116                     // to capture the B-process IOE handles in C process.
       
   117                     ProcessBuilder builderC = new ProcessBuilder(
       
   118                             getCommandArray(APP.C.name()));
       
   119                     processC = builderC.start();
       
   120                     procClaunched = true;
       
   121                 }
       
   122             } catch (IOException ex) {
       
   123                 ex.printStackTrace();
       
   124             }
       
   125         }
       
   126 
       
   127         public void waitFor() throws InterruptedException {
       
   128             processC.waitFor();
       
   129         }
       
   130     }
       
   131 
   101     private static void performA(boolean fileOut) {
   132     private static void performA(boolean fileOut) {
   102         try {
   133         try {
   103             stopC.delete();
   134             stopC.delete();
   104             ProcessBuilder builderB = new ProcessBuilder(
   135             ProcessBuilder builderB = new ProcessBuilder(
   105                     getCommandArray(APP.B.name()));
   136                     getCommandArray(APP.B.name()));
   110                 builderB.redirectOutput(outB);
   141                 builderB.redirectOutput(outB);
   111             }
   142             }
   112             builderB.redirectErrorStream(true);
   143             builderB.redirectErrorStream(true);
   113 
   144 
   114             final CyclicBarrier barrier = new CyclicBarrier(2);
   145             final CyclicBarrier barrier = new CyclicBarrier(2);
   115             Thread procCRunner = new Thread(new Runnable() {
   146             //Create process C in a new thread
   116                 @Override public void run() {
   147             ProcessC processC = new ProcessC(barrier);
   117                     try {
   148             Thread procCRunner = new Thread(processC);
   118                         if (waitBarrier(barrier)) {
       
   119                             waitAbit();
       
   120                             // Run process C next to B ASAP to make an attempt
       
   121                             // to capture the B-process IOE handles in C process.
       
   122                             Runtime.getRuntime().exec(getCommandArray(APP.C.name()));
       
   123                             procClaunched = true;
       
   124                         }
       
   125                     } catch (IOException ex) {
       
   126                         ex.printStackTrace();
       
   127                     }
       
   128                 }
       
   129             });
       
   130             procCRunner.start();
   149             procCRunner.start();
   131 
   150 
   132 
       
   133             if (!waitBarrier(barrier)) {
   151             if (!waitBarrier(barrier)) {
   134                 throw new Error("Catastrophe in process A! Synchronization failed.");
   152                 throw new RuntimeException("Catastrophe in process A! Synchronization failed.");
   135             }
   153             }
   136             // Run process B first.
   154             // Run process B first.
   137             Process processB = builderB.start();
   155             Process processB = builderB.start();
   138 
   156 
   139             while (true) try {
   157             while (true) try {
   142             } catch (InterruptedException ex) {
   160             } catch (InterruptedException ex) {
   143                 continue;
   161                 continue;
   144             }
   162             }
   145 
   163 
   146             if (!procClaunched) {
   164             if (!procClaunched) {
   147                 throw new Error("Catastrophe in process A! C was not launched.");
   165                 throw new RuntimeException("Catastrophe in process A! C was not launched.");
   148             }
   166             }
   149 
   167 
   150             processB.getOutputStream().close();
   168             processB.getOutputStream().close();
   151             processB.getErrorStream().close();
   169             processB.getErrorStream().close();
   152 
   170 
   153             if (fileOut) {
   171             if (fileOut) {
   154                 try {
   172                 try {
   155                     processB.waitFor();
   173                     processB.waitFor();
   156                 } catch (InterruptedException ex) {
   174                 } catch (InterruptedException ex) {
   157                     throw new Error("Catastrophe in process B! B hung up.");
   175                     throw new RuntimeException("Catastrophe in process B! B hung up.");
   158                 }
   176                 }
   159                 System.err.println("Trying to delete [outB.txt].");
   177                 System.err.println("Trying to delete [outB.txt].");
   160                 if (!outB.delete()) {
   178                 if (!outB.delete()) {
   161                     throw new Error("Greedy brother C deadlock! File share.");
   179                     throw new RuntimeException("Greedy brother C deadlock! File share.");
   162                 }
   180                 }
   163                 System.err.println("Succeeded in delete [outB.txt].");
   181                 System.err.println("Succeeded in delete [outB.txt].");
   164             } else {
   182             } else {
   165                 System.err.println("Read stream start.");
   183                 System.err.println("Read stream start.");
   166                 try (BufferedReader in = new BufferedReader( new InputStreamReader(
   184                 boolean isSignalReceived = false;
   167                              processB.getInputStream(), "utf-8")))
   185                 try (BufferedReader in = new BufferedReader(new InputStreamReader(
   168                 {
   186                         processB.getInputStream(), "utf-8"))) {
   169                     String result;
   187                     String result;
   170                     while ((result = in.readLine()) != null) {
   188                     while ((result = in.readLine()) != null) {
   171                         if (!SIGNAL.equals(result)) {
   189                         if (SIGNAL.equals(result)) {
   172                             throw new Error("Catastrophe in process B! Bad output.");
   190                             isSignalReceived = true;
       
   191                         } else {
       
   192                             throw new RuntimeException("Catastrophe in process B! Bad output.");
   173                         }
   193                         }
   174                     }
   194                     }
   175                 }
   195                 }
       
   196                 if (!isSignalReceived) {
       
   197                     throw new RuntimeException("Signal from B was not received");
       
   198                 }
   176                 System.err.println("Read stream finished.");
   199                 System.err.println("Read stream finished.");
   177             }
   200             }
   178             // If JDK-6921885 is not fixed that point is unreachable.
   201             // If JDK-6921885 is not fixed that point is unreachable.
   179             // Test timeout exception.
   202             // Test timeout exception.
   180 
   203 
   181             // write signal file to stop C process.
   204             // write signal file to stop C process.
   182             stopC.createNewFile();
   205             stopC.createNewFile();
       
   206             processC.waitFor();
   183         } catch (IOException ex) {
   207         } catch (IOException ex) {
   184             throw new Error("Catastrophe in process A!", ex);
   208             throw new RuntimeException("Catastrophe in process A!", ex);
       
   209         } catch (InterruptedException ex) {
       
   210             throw new RuntimeException("Process A was interrupted while waiting for C", ex);
   185         }
   211         }
   186     }
   212     }
   187 
   213 
   188     private static void performB() {
   214     private static void performB() {
   189         System.out.println(SIGNAL);
   215         System.out.println(SIGNAL);
   190     }
   216     }
   191 
   217 
   192     private static void performC() {
   218     private static void performC() {
   193         // If JDK-7147084 is not fixed the loop is 5min long.
   219         // If JDK-7147084 is not fixed the loop is 5min long.
   194         for (int i = 0; i < 5*60; ++i) {
   220         for (int i = 0; i < 5 * 60; ++i) {
   195             try {
   221             try {
   196                 Thread.sleep(1000);
   222                 Thread.sleep(1000);
   197                 // check for sucess
   223                 // check for sucess
   198                 if (stopC.exists())
   224                 if (stopC.exists())
   199                     break;
   225                     break;