M
Michael Grove
java gurus,
i'm seeing some odd behavior running a process via Runtime.exec on redhat
linux (seen it on RHEL AS 2.1, 3, 4) with 1.4 and 1.5 JVMs (the only ones
i've tried). if i start a specific process via Runtime.exec and set up
threads to read in the out/err streams, i find that after Process.waitFor()
returns (~5 seconds) the threads are still stuck in InputStream.read(). i
would have expected them to return -1 (or fail with IOExceptions) almost
immediately after process termination. i've tried closing the streams from
the main thread and destroying the process, but that was not enough to break
the threads out of read. i found that if i changed my reader threads to
poll InputStream.available() they will find the streams closed after the
main thread closes them, although available() will return 0 indefinitely if
the main thread fails to close the streams manually.
i'll include the java source below, but the problem seems extremely specific
to the program i'm running in Runtime.exec(). i've been unable to duplicate
the problem with another program. the program is a non-interactive command
line tool (i'll call "cmd") that creates a socket connection to another
process on the same machine and requests an action to be performed (in my
case the action is "-start", passed in on the command line). the program
takes about 5 seconds to complete. upon successful completion no data is
written to standard out/err. the exit code is 0 on success, non-zero on
failure. i can confirm in the process list that the program does terminate
(which Process.waitFor() tells me anyway), and i can also confirm the
program performed the action i expected. i discovered that when my java
process is hung if i terminate the process the command line tool connects to
that will break the threads out of read() with a -1 response. that leads me
to believe that something was not cleaned up when the command line tool
exited. i've also found that if i invoke the command line tool
differently - e.g. i run "cmd -start" after a previous run of "cmd -start"
(close to a no-op) or run "cmd -status" - the java process terminates
normally. so something about the first call to "cmd -start" preventes
InputStream.read() from returning.
some questions:
* after Process.waitFor() returns, what could cause
Process.getInputStream().read() and Process.getErrorStream().read() to block
indefinitely? shouldn't they return -1 or receive IOExceptions almost
immediately?
* any thoughts on what this command line tool might be doing (perhaps not
closing its out/err streams gracefully when it terminates?) that would cause
these reads to block?
thanks.
-mike
import java.io.IOException;
public class cmdstart {
public static void main(String [] args) throws IOException,
InterruptedException {
String cmd = "cmd -start";
Process process = Runtime.getRuntime().exec(cmd);
MyReader outReader = new MyReader(process.getInputStream());
Thread outThread = new Thread(outReader);
outThread.start();
MyReader errReader = new MyReader(process.getErrorStream());
Thread errThread = new Thread(errReader);
errThread.start();
System.out.println("exit code is " + process.waitFor());
//process.destroy();
// process.getInputStream().close();
// process.getErrorStream().close();
outThread.join();
errThread.join();
System.out.println("joins completed");
}
}
import java.io.*;
public class MyReader implements Runnable {
private final InputStream is;
public MyReader(InputStream is) {
this.is = is;
}
public void run() {
// normally would read in while here, but these threads never get any
data -
// they are blocked on the first read() call forever.
int length;
try {
length = is.read();
if (length == -1) {
System.out.println("-1");
return;
}
if (length == 0) {
System.out.println("0");
return;
}
System.out.println("read something");
} catch (Throwable t) {
System.out.println(t);
}
}
}
i'm seeing some odd behavior running a process via Runtime.exec on redhat
linux (seen it on RHEL AS 2.1, 3, 4) with 1.4 and 1.5 JVMs (the only ones
i've tried). if i start a specific process via Runtime.exec and set up
threads to read in the out/err streams, i find that after Process.waitFor()
returns (~5 seconds) the threads are still stuck in InputStream.read(). i
would have expected them to return -1 (or fail with IOExceptions) almost
immediately after process termination. i've tried closing the streams from
the main thread and destroying the process, but that was not enough to break
the threads out of read. i found that if i changed my reader threads to
poll InputStream.available() they will find the streams closed after the
main thread closes them, although available() will return 0 indefinitely if
the main thread fails to close the streams manually.
i'll include the java source below, but the problem seems extremely specific
to the program i'm running in Runtime.exec(). i've been unable to duplicate
the problem with another program. the program is a non-interactive command
line tool (i'll call "cmd") that creates a socket connection to another
process on the same machine and requests an action to be performed (in my
case the action is "-start", passed in on the command line). the program
takes about 5 seconds to complete. upon successful completion no data is
written to standard out/err. the exit code is 0 on success, non-zero on
failure. i can confirm in the process list that the program does terminate
(which Process.waitFor() tells me anyway), and i can also confirm the
program performed the action i expected. i discovered that when my java
process is hung if i terminate the process the command line tool connects to
that will break the threads out of read() with a -1 response. that leads me
to believe that something was not cleaned up when the command line tool
exited. i've also found that if i invoke the command line tool
differently - e.g. i run "cmd -start" after a previous run of "cmd -start"
(close to a no-op) or run "cmd -status" - the java process terminates
normally. so something about the first call to "cmd -start" preventes
InputStream.read() from returning.
some questions:
* after Process.waitFor() returns, what could cause
Process.getInputStream().read() and Process.getErrorStream().read() to block
indefinitely? shouldn't they return -1 or receive IOExceptions almost
immediately?
* any thoughts on what this command line tool might be doing (perhaps not
closing its out/err streams gracefully when it terminates?) that would cause
these reads to block?
thanks.
-mike
import java.io.IOException;
public class cmdstart {
public static void main(String [] args) throws IOException,
InterruptedException {
String cmd = "cmd -start";
Process process = Runtime.getRuntime().exec(cmd);
MyReader outReader = new MyReader(process.getInputStream());
Thread outThread = new Thread(outReader);
outThread.start();
MyReader errReader = new MyReader(process.getErrorStream());
Thread errThread = new Thread(errReader);
errThread.start();
System.out.println("exit code is " + process.waitFor());
//process.destroy();
// process.getInputStream().close();
// process.getErrorStream().close();
outThread.join();
errThread.join();
System.out.println("joins completed");
}
}
import java.io.*;
public class MyReader implements Runnable {
private final InputStream is;
public MyReader(InputStream is) {
this.is = is;
}
public void run() {
// normally would read in while here, but these threads never get any
data -
// they are blocked on the first read() call forever.
int length;
try {
length = is.read();
if (length == -1) {
System.out.println("-1");
return;
}
if (length == 0) {
System.out.println("0");
return;
}
System.out.println("read something");
} catch (Throwable t) {
System.out.println(t);
}
}
}