Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
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) ======================================================================
|