Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-1247602

Process.exitValue(), after an exec(), is unreliable without a Process.waitFor()

    XMLWordPrintable

Details

    • 1.1
    • sparc
    • solaris_2.4
    • Not verified

    Description


      This is fixed in JDK1.1. The fix basically

      1) Has Process.exitValue() do a waitFor() if the process is still alive
      2) Makes it possible to read from the streams even after the process
          has exited

      So this should fix the problem - I ran the example code below
      and it had the following output which seems correct:

      brown@monkey:/home/brown/tests( 997 )% java AnotherProcTest tst1
      ==> exec tst1 then do a read()...
      Do something interesting...
      And then do something else...
      ==> tst1 exited with status 0
      brown@monkey:/home/brown/tests( 998 )% java AnotherProcTest tst2
      ==> exec tst2 then do a read()...
      Do something interesting...
      ==> tst2 exited with status 2
      brown@monkey:/home/brown/tests( 999 )%

      -brown

      -------------------------------------------------------

      If you call exitValue() on a Process object that comes back from Runtime.exec(),
      without doing a waitFor(), the exitValue() becomes unpredictable and/or unattainable.
      For example, if you want to access the Process InputStream, or ErrorStream, until
      execution completes, and then check the exit value, this usually fails because
      you end up in your catch clause. At this point you have no handle to your Process
      object. Further, the java compiler will not allow you to access your Process object
      outside of the 'try' block (becasue it may not have been initialized). But because
      there is no default constructor for UNIXProcess, it's impossible to initialize it
      before the try block. Once inside the try block, execution goes to the catch block
      immediately upon completion on the exec(), unless there is a waitFor(). But if you
      do a waitFor(), then you can't access the process streams.

      Here is some code that illustrates the problem:

      import java.io.*;

      public class Tst {
          public static void main(String argv[]) {
              String Cmd = argv[0];
              char[] buffer = new char[80];
              int c;
              int ex = -1;

              System.out.println("==> exec " + Cmd + " then do a read()...");
              try {
                  Process p = Runtime.getRuntime().exec(Cmd);
                  InputStream is = new BufferedInputStream(p.getInputStream());
                  int i = 0;
                  while ((c = is.read()) >= 0) {
                      if (c == '\\n') {
                           String s = new String(buffer, 0, i);
                           System.out.println(s);
                           i = 0;
                      } else {
                          buffer[i++] = (char)c;
                      }
                  }
                  is.close();
                  ex = p.exitValue();
                  System.out.println("==> " + Cmd + " exited with status " + ex);
              } catch (Exception e) {
                  System.err.println("Exeception: exit status " + ex);
              }
          }
      }

      Here is tst1:
      ---------
      #!/bin/ksh -p

      print Do something interesting...
      print And then do something else...

      Here is tst2:
      ---------
      #!/bin/ksh -p

      print Do something interesting...
      exit 2
      print And then do something else...

      And here is some output from running Tst with each file:
      --------------------------------------------
      butteville 654 : java Tst ./tst1
      ==>exec ./tst1 then do a read()...
      pid 3733 status 0
      Received sigchild for 3733 exit=0
      Do something interesting...
      And then do something else...
      ==> ./tst1 exited with status 0

      butteville 655 : !!
      java Tst ./tst1
      ==>exec ./tst1 then do a read()...
      Do something interesting...
      And then do something else...
      pid 3739 status 0
      Received sigchild for 3739 exit=0
      Exeception: exit status -1


      butteville 652 : java Tst ./tst2
      ==>exec ./tst2 then do a read()...
      pid 3720 status 2
      Received sigchild for 3720 exit=2
      Do something interesting...
      ==> ./tst2 exited with status 2

      butteville 653 : !!
      ==>exec ./tst2 then do a read()...
      Do something interesting...
      pid 3726 status 2
      Received sigchild for 3726 exit=2
      Exeception: exit status -1

      Attachments

        Activity

          People

            tlindholsunw Timothy Lindholm (Inactive)
            duke J. Duke
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: