< prev index next >

test/failure_handler/src/share/classes/jdk/test/failurehandler/action/ActionHelper.java

Print this page
rev 2291 : 8168414: Various timeouthandler fixes


 147 
 148     private void addJdks(Path[] jdkPaths) {
 149         if (jdkPaths != null && jdkPaths.length != 0) {
 150             Path[] result = new Path[jdkPaths.length + paths.length];
 151             for (int i = 0; i < jdkPaths.length; ++i) {
 152                 result[i] = jdkPaths[i].resolve("bin");
 153             }
 154             System.arraycopy(paths, 0, result, jdkPaths.length, paths.length);
 155             paths = result;
 156         }
 157     }
 158 
 159     private ExitCode run(PrintWriter log, Writer out, ProcessBuilder pb,
 160                     ActionParameters params) {
 161         char[] lineChars = new char[40];
 162         Arrays.fill(lineChars, '-');
 163         String line = new String(lineChars);
 164         Stopwatch stopwatch = new Stopwatch();
 165         stopwatch.start();
 166 
 167         log.printf("%s%n[%tF %<tT] %s%n%1$s%n", line, new Date(), pb.command());

 168         Process process;
 169         KillerTask killer;
 170 
 171         ExitCode result = ExitCode.NEVER_STARTED;
 172 
 173         try {
 174             process = pb.start();
 175             killer = new KillerTask(process);
 176             killer.schedule(params.timeout);
 177             Utils.copyStream(new InputStreamReader(process.getInputStream()),
 178                     out);
 179             try {
 180                 result = new ExitCode(process.waitFor());
 181                 killer.cancel();
 182             } catch (InterruptedException e) {
 183                 Thread.currentThread().interrupt();
 184                 if (!killer.cancel()) {
 185                     log.println(
 186                             "WARNING: interrupted when waiting for the tool:");
 187                     e.printStackTrace(log);
 188                 }

 189             }
 190             if (killer.hasTimedOut()) {
 191                 log.printf(
 192                         "WARNING: tool timed out: killed process after %d ms%n",
 193                         TimeUnit.MILLISECONDS.toMicros(params.timeout));
 194                 result = ExitCode.TIMED_OUT;
 195             }
 196         } catch (IOException e) {

 197             e.printStackTrace(log);
 198             result = ExitCode.LAUNCH_ERROR;
 199         }
 200 
 201         stopwatch.stop();
 202         log.printf("%s%n[%tF %<tT] exit code : %d time : %d ms%n%1$s%n",
 203                 line, new Date(), result.value,
 204                 TimeUnit.MILLISECONDS.toSeconds(stopwatch.getElapsedTimeNs()));
 205         return result;
 206     }
 207 
 208     public void runPatternAction(SimpleAction action, HtmlSection section) {
 209         if (action != null) {
 210             HtmlSection subSection = action.getSection(section);
 211             PrintWriter log = subSection.getWriter();
 212             ProcessBuilder pb = action.prepareProcess(log, this);
 213             exec(subSection, pb, action.getParameters());
 214         }
 215     }
 216 
 217     public void runPatternAction(PatternAction action, HtmlSection section,
 218                                  String value) {
 219         if (action != null) {
 220             ProcessBuilder pb = action.prepareProcess(section, this, value);
 221             HtmlSection subSection = action.getSection(section);
 222             exec(subSection, pb, action.getParameters());
 223         }
 224     }


 230         }
 231         pb.redirectErrorStream(true);
 232         boolean result = false;
 233         String pidStr = "" + pid;
 234         try {
 235             Process process = pb.start();
 236             try (BufferedReader reader = new BufferedReader(
 237                     new InputStreamReader(process.getInputStream()))) {
 238                 String line;
 239                 while ((line = reader.readLine()) != null){
 240                     if (pidStr.equals(line)) {
 241                         result = true;
 242                     }
 243                 }
 244             }
 245             process.waitFor();
 246         } catch (IOException e) {
 247             log.printf("WARNING: can't run jps : %s%n", e.getMessage());
 248             e.printStackTrace(log);
 249         } catch (InterruptedException e) {
 250             Thread.currentThread().interrupt();
 251             e.printStackTrace(log);
 252         }
 253         return result;
 254     }
 255 
 256     private static class KillerTask extends TimerTask {
 257         private static final Timer WATCHDOG = new Timer("WATCHDOG", true);
 258         private final Process process;
 259         private boolean timedOut;
 260 
 261         public KillerTask(Process process) {
 262             this.process = process;
 263         }
 264 
 265         public void run() {
 266             try {
 267                 process.exitValue();
 268             } catch (IllegalThreadStateException e) {
 269                 // !prepareProcess.isAlive()
 270                 process.destroy();
 271                 timedOut = true;
 272             }
 273         }
 274 
 275         public boolean hasTimedOut() {
 276             return timedOut;
 277         }
 278 
 279         public void schedule(long timeout) {
 280             if (timeout > 0) {
 281                 WATCHDOG.schedule(this, timeout);
 282             }
 283         }
 284     }
 285 
 286     private void exec(HtmlSection section, ProcessBuilder process,
 287                       ActionParameters params) {
 288         if (process == null) {
 289             return;
 290         }
 291         PrintWriter sectionWriter = section.getWriter();
 292         if (params.repeat > 1) {
 293             for (int i = 0, n = params.repeat; i < n; ++i) {
 294                 HtmlSection iteration = section.createChildren(
 295                         String.format("iteration_%d", i));
 296                 PrintWriter writer = iteration.getWriter();
 297                 ExitCode exitCode = run(writer, writer, process, params);
 298                 if (params.stopOnError && !ExitCode.OK.equals(exitCode)) {
 299                     sectionWriter.printf(
 300                             "ERROR: non zero exit code[%d] -- break.",
 301                             exitCode.value);
 302                     break;
 303                 }


 304                 try {
 305                     Thread.sleep(params.pause);
 306                 } catch (InterruptedException e) {
 307                     Thread.currentThread().interrupt();

 308                     e.printStackTrace(sectionWriter);
 309                 }
 310             }

 311         } else {
 312             run(section.getWriter(), section.getWriter(), process, params);
 313         }
 314     }
 315 
 316     /**
 317      * Special values for prepareProcess exit code.
 318      *
 319      * <p>Can we clash with normal codes?
 320      * On Solaris and Linux, only [0..255] are returned.
 321      * On Windows, prepareProcess exit codes are stored in unsigned int.
 322      * On MacOSX no limits (except it should fit C int type)
 323      * are defined in the exit() man pages.
 324      */
 325     private static class ExitCode {
 326         /** Process exits gracefully */
 327         public static final ExitCode OK = new ExitCode(0);
 328         /** Error launching prepareProcess */
 329         public static final ExitCode LAUNCH_ERROR = new ExitCode(-1);
 330         /** Application prepareProcess has been killed by watchdog due to timeout */




 147 
 148     private void addJdks(Path[] jdkPaths) {
 149         if (jdkPaths != null && jdkPaths.length != 0) {
 150             Path[] result = new Path[jdkPaths.length + paths.length];
 151             for (int i = 0; i < jdkPaths.length; ++i) {
 152                 result[i] = jdkPaths[i].resolve("bin");
 153             }
 154             System.arraycopy(paths, 0, result, jdkPaths.length, paths.length);
 155             paths = result;
 156         }
 157     }
 158 
 159     private ExitCode run(PrintWriter log, Writer out, ProcessBuilder pb,
 160                     ActionParameters params) {
 161         char[] lineChars = new char[40];
 162         Arrays.fill(lineChars, '-');
 163         String line = new String(lineChars);
 164         Stopwatch stopwatch = new Stopwatch();
 165         stopwatch.start();
 166 
 167         log.printf("%s%n[%tF %<tT] %s timeout=%s%n%1$s%n", line, new Date(), pb.command(), params.timeout);
 168 
 169         Process process;
 170         KillerTask killer;
 171 
 172         ExitCode result = ExitCode.NEVER_STARTED;
 173 
 174         try {
 175             process = pb.start();
 176             killer = new KillerTask(process);
 177             killer.schedule(params.timeout);
 178             Utils.copyStream(new InputStreamReader(process.getInputStream()),
 179                     out);
 180             try {
 181                 result = new ExitCode(process.waitFor());

 182             } catch (InterruptedException e) {
 183                 log.println("WARNING: interrupted when waiting for the tool:%n");



 184                 e.printStackTrace(log);
 185             } finally {
 186                 killer.cancel();
 187             }
 188             if (killer.hasTimedOut()) {
 189                 log.printf(
 190                         "WARNING: tool timed out: killed process after %d ms%n",
 191                         params.timeout);
 192                 result = ExitCode.TIMED_OUT;
 193             }
 194         } catch (IOException e) {
 195             log.printf("WARNING: caught IOException while running tool%n");
 196             e.printStackTrace(log);
 197             result = ExitCode.LAUNCH_ERROR;
 198         }
 199 
 200         stopwatch.stop();
 201         log.printf("%s%n[%tF %<tT] exit code: %d time: %d ms%n%1$s%n",
 202                 line, new Date(), result.value,
 203                 TimeUnit.NANOSECONDS.toMillis(stopwatch.getElapsedTimeNs()));
 204         return result;
 205     }
 206 
 207     public void runPatternAction(SimpleAction action, HtmlSection section) {
 208         if (action != null) {
 209             HtmlSection subSection = action.getSection(section);
 210             PrintWriter log = subSection.getWriter();
 211             ProcessBuilder pb = action.prepareProcess(log, this);
 212             exec(subSection, pb, action.getParameters());
 213         }
 214     }
 215 
 216     public void runPatternAction(PatternAction action, HtmlSection section,
 217                                  String value) {
 218         if (action != null) {
 219             ProcessBuilder pb = action.prepareProcess(section, this, value);
 220             HtmlSection subSection = action.getSection(section);
 221             exec(subSection, pb, action.getParameters());
 222         }
 223     }


 229         }
 230         pb.redirectErrorStream(true);
 231         boolean result = false;
 232         String pidStr = "" + pid;
 233         try {
 234             Process process = pb.start();
 235             try (BufferedReader reader = new BufferedReader(
 236                     new InputStreamReader(process.getInputStream()))) {
 237                 String line;
 238                 while ((line = reader.readLine()) != null){
 239                     if (pidStr.equals(line)) {
 240                         result = true;
 241                     }
 242                 }
 243             }
 244             process.waitFor();
 245         } catch (IOException e) {
 246             log.printf("WARNING: can't run jps : %s%n", e.getMessage());
 247             e.printStackTrace(log);
 248         } catch (InterruptedException e) {
 249             log.printf("WARNING: interrupted%n");
 250             e.printStackTrace(log);
 251         }
 252         return result;
 253     }
 254 
 255     private static class KillerTask extends TimerTask {
 256         private static final Timer WATCHDOG = new Timer("WATCHDOG", true);
 257         private final Process process;
 258         private boolean timedOut;
 259 
 260         public KillerTask(Process process) {
 261             this.process = process;
 262         }
 263 
 264         public void run() {
 265             try {
 266                 process.exitValue();
 267             } catch (IllegalThreadStateException e) {
 268                 process.destroyForcibly();

 269                 timedOut = true;
 270             }
 271         }
 272 
 273         public boolean hasTimedOut() {
 274             return timedOut;
 275         }
 276 
 277         public void schedule(long timeout) {
 278             if (timeout > 0) {
 279                 WATCHDOG.schedule(this, timeout);
 280             }
 281         }
 282     }
 283 
 284     private void exec(HtmlSection section, ProcessBuilder process,
 285                       ActionParameters params) {
 286         if (process == null) {
 287             return;
 288         }
 289         PrintWriter sectionWriter = section.getWriter();
 290         if (params.repeat > 1) {
 291             for (int i = 0, n = params.repeat; i < n; ++i) {
 292                 HtmlSection iteration = section.createChildren(
 293                         String.format("iteration_%d", i));
 294                 PrintWriter writer = iteration.getWriter();
 295                 ExitCode exitCode = run(writer, writer, process, params);
 296                 if (params.stopOnError && !ExitCode.OK.equals(exitCode)) {
 297                     sectionWriter.printf(
 298                             "ERROR: non zero exit code[%d] -- break.",
 299                             exitCode.value);
 300                     break;
 301                 }
 302                 // sleep, if this is not the last iteration
 303                 if (i < n - 1) {
 304                     try {
 305                         Thread.sleep(params.pause);
 306                     } catch (InterruptedException e) {
 307                         sectionWriter.printf(
 308                                 "WARNING: interrupted while sleeping between invocations");
 309                         e.printStackTrace(sectionWriter);
 310                     }
 311                 }
 312             }
 313         } else {
 314             run(section.getWriter(), section.getWriter(), process, params);
 315         }
 316     }
 317 
 318     /**
 319      * Special values for prepareProcess exit code.
 320      *
 321      * <p>Can we clash with normal codes?
 322      * On Solaris and Linux, only [0..255] are returned.
 323      * On Windows, prepareProcess exit codes are stored in unsigned int.
 324      * On MacOSX no limits (except it should fit C int type)
 325      * are defined in the exit() man pages.
 326      */
 327     private static class ExitCode {
 328         /** Process exits gracefully */
 329         public static final ExitCode OK = new ExitCode(0);
 330         /** Error launching prepareProcess */
 331         public static final ExitCode LAUNCH_ERROR = new ExitCode(-1);
 332         /** Application prepareProcess has been killed by watchdog due to timeout */


< prev index next >