JDK-4254231 : Process.waitFor() fails to return - still a bug - 4098442 is NOT fixed!
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 1.2.2
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: windows_nt
  • CPU: x86
  • Submitted: 1999-07-15
  • Updated: 1999-10-14
  • Resolved: 1999-10-14
Related Reports
Relates :  
Description

Name: rlT66838			Date: 07/14/99


The Process.waitFor() method fails to return. This problem has previously been reported under bug id 4098442, which states it is "fixed". However, the following java code illustrates that it is still a problem. Both JDK 1.2.1 and 1.2.2 show the same "hanging" behavior on Windows NT 4.0, service pack 4.

The first part of this test program defines a method called
"doWaitFor()" which can be used as a workaround to this bug.
This method is based upon the same workaround proposed under
bug id 4098442. I am providing this encapsulated version here
which other users can easily cut and paste into their own
programs.

When using this test program, the "command" string in the
main() method should be changed to the proper path for
your installed JDK.

By executing "java TestExec 1" the program will attempt to
use Process.WaitFor(). This method hangs.

If the program is re-run using "java TestExec 2" the program
will use the "doWaitFor()" workaround, which does not hang.

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;

public class TestExec {

   /** 
    * Method to perform a "wait" for a process and return its exit value.
    * This is a workaround for <CODE>process.waitFor()</CODE> never returning.
    */
   public static int doWaitFor(Process p) {

      int exitValue = -1;  // returned to caller when p is finished

      try {

         InputStream in  = p.getInputStream();
         InputStream err = p.getErrorStream();

         boolean finished = false; // Set to true when p is finished

         while( !finished) {
            try {

               while( in.available() > 0) {

                  // Print the output of our system call
                  Character c = new Character( (char) in.read());
                  System.out.print( c);
               }

               while( err.available() > 0) {

                  // Print the output of our system call
                  Character c = new Character( (char) err.read());
                  System.out.print( c);
               }

               // Ask the process for its exitValue. If the process
               // is not finished, an IllegalThreadStateException
               // is thrown. If it is finished, we fall through and
               // the variable finished is set to true.

               exitValue = p.exitValue();
               finished  = true;

            } 
               catch (IllegalThreadStateException e) {

                  // Process is not finished yet;
                  // Sleep a little to save on CPU cycles
                  Thread.currentThread().sleep(500);
               }
         }


      } 
         catch (Exception e) {

            // unexpected exception!  print it out for debugging...
            System.err.println( "doWaitFor(): unexpected exception - " + e.getMessage());
         }

      // return completion status to caller
      return exitValue;
   }



   public static void main (String[] args) {

      if (args.length == 0) {
         System.out.println ("Usage:  java TestExec 1    -- will test Process.waitFor()");
         System.out.println ("        java TestExec 2    -- will test doWaitFor() workaround");
         return;
      }

      try {
         String command = "e:\\jdk1.2.2\\bin\\java";  // change to your "java" location
         int exitValue  = -1;

         System.out.println("--->Executing " + command);
         Process process = Runtime.getRuntime().exec(command);

         if (args[0].equals("1")) {

            System.out.println("--->Waiting for completion of " + command + " using process.waitFor()...");
            exitValue = process.waitFor();
         }
         else {

            System.out.println("--->Waiting for completion of " + command + " using doWaitFor() workaround...");
            exitValue = doWaitFor( process);
         }

         System.out.println("--->Done Waiting, exit value = " + exitValue);

      } 
         catch(Exception e) {
            System.out.println("--->Exception occurred: " + e.getMessage());
         }
   }

}
(Review ID: 85587) 
======================================================================

Comments
WORK AROUND Name: rlT66838 Date: 07/14/99 See test program. ======================================================================
11-06-2004

EVALUATION The issue reported in 4098442 is not a bug, as made clear in the comments and evaluation there. If you run a process that produces output, you must consume that output in order to prevent the pipe from filling and the process blocking. The example shown here shows simply that consuming the output does avoid the issue, as expected. william.maddox@Eng 1999-10-13
13-10-1999