JDK-4202880 : (process) Can't feed data to stdin of child process on Win NT
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 1.0,1.1.7
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS: solaris_2.5.1,solaris_2.6
  • CPU: x86,sparc
  • Submitted: 1999-01-13
  • Updated: 2002-06-13
  • Resolved: 2002-06-13
Related Reports
Relates :  
Description
Bug 4183312 was filed against Java WorkShop.  I have concluded that this
is a JDK problem and not a Java WorkShop problem.  Attached are two sample
programs to demonstrate the problem.  These two programs work as expected
on Solaris, Win95, Win98 but fail on WinNT.  On WinNT the child process
never sees any data coming on stdin.

The two programs are Bug4183312 and Cat.  The Cat program is a simple
verion of cat written in Java.  It copies its stdin (System.in) to its
stdout (System.out).  The Bug4183312 program execs Cat, feeds it 5 lines
of text and then reads 5 lines of text from Cat's stdout.

On WinNT the data being feed into Cat's stdin never gets to Cat.
It appears that the process creation has messed up in some way
thereby disabling the child process's stdin.

Here is the source to the two programs.  They should be put in the
same directory and compiled so that the .class files are next to the
.java files.  Each of the source files contains one pathname that is
the pathname of the directory where the .java and .class file live.
I ran the tests from a shell on Solaris and from a MSDOS window on
the WinTel platforms.  

======= Bug4183312.java ==========
import java.io.*;

public class Bug4183312 {

    /**
     * Constructor.
     */
    public Bug4183312 () {
    }

    public static void main(String args[]) throws Exception {
        System.err.println("Getting started, ready to exec");
        String javaHome = System.getProperty("java.home");
        String javaExe = javaHome + File.separator +
            "bin" + File.separator + "java";
        /*
      	 * Change the /home/evan/jws/Bug4183312 directory to
         * the directory where the .class files are
	 */
        String classPath = javaHome + File.separator +
            "lib" + File.separator + "classes.zip" +
            File.pathSeparator + "/home/evan/jws/Bug4183312";
        String cmd = javaExe + " -classpath " + classPath + " Cat";
        System.err.println("cmd = " + cmd);
        Process proc = Runtime.getRuntime().exec(cmd);
        System.err.println("After exec");
        DataInputStream catStdout = new DataInputStream(proc.getInputStream());
        PrintStream catStdin = new PrintStream(proc.getOutputStream());
        System.err.println("After setting up stdin and stdout");

        /*
         * Send <n> lines to the cat program
         */
        int nLines = 5;
        System.err.println("Ready to pump " + nLines + " lines of data to cat");
        for (int i = 0; i < nLines; i++) {
            catStdin.println("line " + i);
        }
        catStdin.println("EOF");
        catStdin.flush();
        catStdin.close();

        /*
         * Read the 5 lines from the cat program
         */
        System.err.println("Ready to read " + nLines + " lines of data from cat"
);
        for (int i = 0; i < nLines; i++) {
            String line = catStdout.readLine();
            System.out.println("From cat: " + line);
        }

        System.err.println("Done reading");
        proc.waitFor();
        System.err.println("Child process has terminated");
    }
}

======== Cat.java ============
import java.io.*;

public class Cat {

    /**
     * Constructor.
     */
    public Cat () {
    }

    public static void main(String args[]) {
        BufferedReader stdin = new BufferedReader(
                               new InputStreamReader(
                               System.in));
        PrintStream log = null;

        try {
	    /*
	     * Change the /home/evan/jws/Bug4183312 to one that is 
	     * convenient to you.  I suggest making it the same as
	     * the directory where the sources are.
	     */
            log = new PrintStream(new FileOutputStream("/home/evan/jws/Bug4183312/cat.txt")
);
        } catch (Exception e) {
            System.err.println("Could not open cat.txt");
            System.exit(1);
        }
        System.err.println("Starting cat");
        String line;

        try {
            line = stdin.readLine();
            while (line != null) {
                if (line.equals("EOF")) {
                    break;
                }
                System.out.println(line);
                log.println(line);
                log.flush();
                line = stdin.readLine();
            }
            log.close();

        } catch (Exception e) {}
        System.exit(0);
    }
}


Comments
EVALUATION The description is correct. The problem has been fixed in 1.2, however it has been incorprated into 11 for some reason. It should be fixed in 118. The technical background is the child process inherits both ends of pipe. So the pipe will be kept open even the parent process has closed it. Because both parent and child own both ends of a pipe, weird result may happen. ###@###.### 1999-01-13 The fix is in JDK1.2. However considering the risk, we decide not to put it into 1.1.x code base for now. ###@###.### 1999-02-22 Since the bug is fixed in 1.2 and since 1.1.x is not relevant any more, I am closing this bug,. ###@###.### 2002-06-13
22-02-1999