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

(process) "Exec"ed processes hang on NT when reading the standard input

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P5
    • Resolution: Won't Fix
    • Affects Version/s: 1.1.5, 1.1.6, 1.2.2
    • Fix Version/s: None
    • Component/s: core-libs
    • Labels:
    • Subcomponent:
    • CPU:
      x86
    • OS:
      windows_nt

      Description

      Name: joT67522 Date: 01/12/98

      On Windows NT, closing the "input" stream of a
      subprocess doesn't work as expected. That is, if
      I "exec" a command that tries to read from the
      standard input till the end-of-stream,
      it will hang. For instance,

      class test {
        public static void main (String [] args) {
          try {
            Process proc = Runtime.getRuntime().exec("cat");
            proc.getOutputStream().close();
            proc.waitFor();
          }
            catch (Exception e) { System.out.println("Exception"); }
        }
      }

      The "close" goes unnoticed by the "exec"ed
      process. I have tried this with several commands
      (some that I wrote and compiled myself and some
      system commands). Every command that tries to
      read from the standard input hangs (doesn't get
      an end-of-stream notification).

      Identical source code runs fine on Solaris (both
      on Sparcstations and x86). I have not tried it
      under Windows 95.

      I also tried writing explicitly an end-of-file
      character (-1) to the stream, with no luck.

      This is an important problem (for me, that is :-).
      It means I cannot "exec" an application in binary
      format which reads data from the standard input.
      (Review ID: 22647)
      ======================================================================

      Here is another test case submitted via the web which sends the output
      of exec("ls -ls") to the input of "cat". On Solaris it works great,
      but on NT it hangs trying to read the output of the "cat" Process.
      brian.klock@eng 1998-06-18

      //----------------------proc_io.java-------------------------
      import java.io.*;
      public class proc_io {
      public static void main(String args[]) throws IOException {
      Process proc1 = Runtime.getRuntime().exec("ls -ls");
      Process proc2 = Runtime.getRuntime().exec("sort");
      // What state is proc2 in right now? Is it waiting for input, or has it finished?

      BufferedReader proc1StdOut = new BufferedReader(new InputStreamReader(proc1.getInputStream()));
      BufferedReader proc2StdOut = new BufferedReader(new InputStreamReader(proc2.getInputStream()));
      PrintWriter proc2StdIn = new PrintWriter(proc2.getOutputStream());
      String line1StdOut;
      String line2StdOut;

      // copy stdout from proc1 to stdin on proc2
      while( true ) {
      line1StdOut=proc1StdOut.readLine();
      if( line1StdOut==null )
      break;
      proc2StdIn.println(line1StdOut);
      proc2StdIn.flush();
      }

                      proc2StdIn.close();

      // dump stdout on proc2 to screen
      while( true ) {
      // next line goobers in java.io.FileInputStream.read(byte b[]) which calls readBytes(byte[], int, int)
      line2StdOut=proc2StdOut.readLine();
      if( line2StdOut==null )
      break;
      System.out.println( line2StdOut );
      }
      proc1.destroy();
      proc2.destroy();
      }
      }

      ======================================================================



      Name: mc57594 Date: 11/11/99


      Under certain circumstances, the input stream of a Process created by Runtime.exec() (obtained from Process.getInputStream()) never indicates end-of-file, even though the process runs to completion. Therefore the exec'ing process, which is copying the stream, hangs waiting for more stream data.

      I'm running the latest JDK 1.2.2. This problem happens both with HotSpot and with the classic JVM. It happens under Windows 98 (the 2nd edition release) and Windows NT4 (sp5). My test input and output are very small, so I'm sure blocking due to buffer overflow is not an issue.

      Version info:

      >java -version
      java version "1.2.2"
      HotSpot VM (1.0.1, mixed mode, build g)

      >java -fullversion
      java full version "JDK-1.2.2-W"

      >java -classic -version
      java version "1.2.2"
      Classic VM (build JDK-1.2.2-W, native threads, symcjit)

      >java -classic -fullversion
      java full version "JDK-1.2.2-W"

      The circumstances, as best I can figure out, are that both of the following must be true:

        - The process being run by Runtime.exec() is "java" (it does
          not seem to hang for non-java processes).
        - The process reads from standard input.

      I have some small test programs that can reproduce this -- I'll include them after this text. They are:

      run.java -- a very simple program to run another process. It
                  takes an optional -i <input file> option, and passes
                  remaining arguments as a String[] to exec().
      cp.java -- a program to copy standard input to standard output
      out.java -- a program to print a short message (reads no input)

      Running:

          java run -i hello.txt java cp

      hangs up. (hello.txt is a file with contents "Hello.\n".) The exec'd cp.java process completes its loop that reads standard input, sends all of its standard output, and the process presumably terminates. However, run.java never completes its loop to copy the process's output.

      The interesting thing is that this only seems to happen when exec'ing a "java" process. A similar "cp" program created most any other way works fine. It seems that the JVM is not doing something at process completion that "normal" processes do.

      Also, if the java process does not read from standard input, it works okay. Using the out.java program:

          java run java out

      works okay. Also:

          java run -i hello.txt java out

      works okay too, so even though it tries to send data to the exec'd process's standard input, things terminate normally as long as the exec'd process does not actually _read_ from standard input.

      By the way, (yeah I know I'm supposed to focus on one problem) on DOS only (not NT), the run.java process has to send a ^Z character at the end of its input, otherwise the exec'd cp.java process does not detect end-of-file on its input!

      Here are my little test programs:

      ////////// run.java

      import java.io.*;

      class run {

      public static void main(String[] args) throws Exception {
      //
      // Create an input stream if -i option.
      //
      String inputFile = null;
      if (args[0].equals("-i")) {
      inputFile = args[1];
      String[] newArgs = new String[args.length - 2];
      System.arraycopy(args, 2, newArgs, 0, args.length - 2);
      args = newArgs;
      }
      //
      // Start a process using command line arguments as the String
      // array passed to Runtime.exec().
      //
      Process p = Runtime.getRuntime().exec(args);
      int c;
      //
      // If an input file specified, copy input to the process.
      //
      if (inputFile != null) {
      FileInputStream in = new FileInputStream(inputFile);
      while ((c = in.read()) >= 0) {
      System.out.println("in: '" + (char)c + '\'');
      p.getOutputStream().write(c);
      }
      System.out.println("in: Done.");
      //p.getOutputStream().write('\u001a'); // ^Z
      p.getOutputStream().flush();
      }
      //
      // Copy output from process.
      //
      while ((c = p.getInputStream().read()) >= 0) {
      System.out.println("out: '" + (char)c + '\'');
      //System.out.write(c);
      }
      System.out.println("out: Done.");
      //
      // Wait for process to complete.
      //
      p.waitFor();
      System.out.println("process: Done.");
      }

      }


      ////// cp.java

      class cp {

      public static void main(String[] args) throws Exception {
      int c;
      while ((c = System.in.read()) >= 0) {
      System.out.write(c);
      }
      System.out.println("Done.");
      }

      }


      ///////// out.java

      class out {

      public static void main(String[] args) {
      System.out.println("Out.");
      }

      }
      (Review ID: 94279)
      ======================================================================

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              martin Martin Buchholz
              Reporter:
              johsunw Joon Oh (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: