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

thread blocks on I/O to subprocess

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P3 P3
    • None
    • 1.1.3
    • core-libs
    • None
    • sparc
    • solaris_2.5.1



      Name: rlT66838 Date: 08/18/97


      We encountered a bug in java.lang.Process in I/O to a subprocess. The
      following classes demonstrate the bug. Class Subprocess starts an
      external command and copies data from System.in to the stdin of the
      child process and in parallel from the child's stdout to System.out.
      The copying is done by instances of class Pump which is a subclass of
      Thread.

      If we start Subprocess with

        java Subprocess cat

      we expect that the input typed on System.in be output on System.out
      immediatly, because there should be no buffering like typing directly
      into cat.

      $> java Subprocess cat
      Creating out pump.
      Starting out pump.
      Creating in pump.
      Starting in pump.
      Starting pump out.
      hello <--- typed in from keyboard
      Pump out (read).
      Pump out (write).
      Pump out (flush).
      world <--- typed in from keyboard
      Pump out (read).
      Pump out (write).
      Pump out (flush).
      Pump out (read). <--- typed control-D for EOF
      Pump out (nothing read).
      Starting pump in.
      Pump in (read).
      Pump in (write).
      hello
      world
      Pump in (flush).
      Pump in (read).
      Pump in (nothing read).

      Tracing the VM with truss reports that the process is hanging in a
      read system call:

      ...
      read(0, 0xEE337D80, 2048) (sleeping...)
      hello
      read(0, " h e l l o\n", 2048) = 6
      Pump out (read).write(2, " P u m p o u t ( r e".., 16) = 16

      write(2, "\n", 1) = 1
      Pump out (write).write(2, " P u m p o u t ( w r".., 17) = 17

      write(2, "\n", 1) = 1
      Pump out (flush).write(2, " P u m p o u t ( f l".., 17) = 17

      write(2, "\n", 1) = 1
      write(12, " h e l l o\n", 6) = 6
          Received signal #22, SIGPOLL [caught]
            siginfo: SIGPOLL POLL_IN fd=1357097392 band=0
      poll(0x000229B0, 3, 0) = 3
      setcontext(0xEF201518)
      read(0, 0xEE337D80, 2048) (sleeping...)
      ...


      Another effect of this bug may be observed by starting the shell
      script 'loop.sh' as a subprocess. The VM hangs until an EOF (control
      D) arrives in on its stdin, although the command begins to output data
      right after it is started. One would expect the second thread to
      report the received data immediately and independently from the child's
      input stream. With truss one can see in this case too, that the VM
      process is hanging on a read system call.

      This bug does not appear under Linux using the JDK-1.1.1v3 port. On
      Linux we see the expected behavior:

      $> java Subprocess cat
      Creating out pump.
      Starting out pump.
      Creating in pump.
      Starting in pump.
      Starting pump out.
      Starting pump in.
      hello <--- typed in from keyboard
      Pump out (read).
      Pump out (write).
      Pump out (flush).
      Pump in (read).
      Pump in (write).
      hello
      Pump in (flush).
      world <--- typed in from keyboard
      Pump out (read).
      Pump out (write).
      Pump out (flush).
      Pump in (read).
      Pump in (write).
      world
      Pump in (flush).
      Pump out (read). <--- typed control-D from keyboard
      Pump out (nothing read).
      Pump in (read).
      Pump in (nothing read).

      The output from loop.sh is also reported immediatly under Linux:

      $> java Subprocess loop.sh
      Creating out pump.
      Starting out pump.
      Creating in pump.
      Starting in pump.
      Starting pump out.
      Starting pump in.
      Pump in (read).
      Pump in (write).
      message 0
      Pump in (flush).
      Pump in (read).
      Pump in (write).
      message 1
      Pump in (flush).
      Pump in (read).
      Pump in (write).
      message 2
      Pump in (flush).
      Pump in (read).
      Pump in (write).
      message 3
      ...


      Sources:

      Pump.java
      -----8<--------8<--------8<--------8<--------8<--------8<--------8<-------
      // used packages
      import java.lang.*;
      import java.io.*;

      // class Pump copies data from the given InputStream to an OutputStream.
      class Pump extends Thread {

        private InputStream in;
        private OutputStream out;
        private String name;

        public Pump( InputStream is, OutputStream os, String pname ) {
          in = is;
          out = os;
          name = pname;
        }

        public void run () {
          int len;
          byte buf[] = new byte[1024];

          try {
            System.err.println("Starting pump " + name + ".");
            while (true) {
      len = in.read(buf);
      System.err.println("Pump " + name + " (read).");

      if (len >= 1 ) {
      System.err.println("Pump " + name + " (write).");
      out.write(buf, 0, len);

      System.err.println("Pump " + name + " (flush).");
      out.flush();

      } else {

      System.err.println("Pump " + name + " (nothing read).");

      out.close();
      break;
      }
            }
          }
          catch (Exception e) {
            System.err.println(e);
            e.printStackTrace();
          }
        }
      }
      -----8<--------8<--------8<--------8<--------8<--------8<--------8<-------

      Subprocess.java
      -----8<--------8<--------8<--------8<--------8<--------8<--------8<-------
      // used packages
      import java.lang.*;
      import java.io.*;

      public class Subprocess {

        // spawn external process and connect a Pump on input and output
        // stream to copy data to System.in and System.out, respectively
        public static void main(String[] args) {

          Process subprocess;
          try {
            subprocess = Runtime.getRuntime().exec( args[0] );
          }
          catch (IOException ioe) {
            System.err.println("Exception while spawning subprocess: " + ioe);
            return;
          }
          OutputStream out = subprocess.getOutputStream();
          InputStream in = subprocess.getInputStream();

          System.err.println("Creating out pump.");
          Pump outPump = new Pump( System.in, out, "out" );
          System.err.println("Starting out pump.");
          outPump.start();

          System.err.println("Creating in pump.");
          Pump inPump = new Pump( in, System.out, "in" );
          System.err.println("Starting in pump.");
          inPump.start();
        }
      }
      -----8<--------8<--------8<--------8<--------8<--------8<--------8<-------

      loop.sh
      -----8<--------8<--------8<--------8<--------8<--------8<--------8<-------
      #!/bin/sh
      # This script outputs a messages to stdout.
      # It sleeps a while after each send.

      for i in 0 1 2 3 4 5 6 7 8 9
      do
        echo "message $i"
        sleep 3
      done
      -----8<--------8<--------8<--------8<--------8<--------8<--------8<-------

      company - TU Darmstadt, Germany , email - ###@###.###
      ======================================================================

            never Tom Rodriguez
            rlewis Roger Lewis (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: