Whenever you run a child process, the following tow things need to be ensured:
a) The parent process should monitor the child process.
b) The parent process should wait for the child process to complete to check its state.
To achieve the first, you should make a mandatory commitment to consume the child process output stream and the error streams, at the same time. Apart from this, the parent process needs to wait for the child process to complete its execution before getting its exit code.
To consume the Output and error streams, you could create a runnable which reads both these streams simaltaneously, and logs the output to a file.
class StreamConsumer implements Runnable
{
private InputStream is;
private String outputFile;
StreamConsumer(InputStream is, String outputFile)
{
this.is = is;
this.outputFile = outputFile;
}
public void run()
{
InputStreamReader isr = null;
BufferedReader br = null;
FileOutputStream fos = null;
BufferedWriter bufferedWriter = null;
char[] characterBuffer = null;
try
{
characterBuffer = new char[1024];
isr = new InputStreamReader(is,"UTF-8");
br = new BufferedReader(isr);
fos = new FileOutputStream(outputFile);
bufferedWriter = new BufferedWriter(new OutputStreamWriter(fos,"UTF-8"));
LOGGER.info("Writing to op file: "+ this.outputFile);
int readCharacters = -1;
while ((readCharacters = br.read(characterBuffer,0,1024)) != -1)
{
String sw = new String(characterBuffer,0,readCharacters);
/*
* To ignore empty chunks
*/
if(sw != null && sw.trim().length() > 0)
{
bufferedWriter.write(sw.toString());
}
characterBuffer = new char[1024];
}
LOGGER.info("Done Writing to op file: "+ this.outputFile);
}
catch (Exception ioe)
{
LOGGER.error("IOException ", ioe);
}
finally
{
if(br != null)
{
try {
br.close();
} catch (IOException e) {
LOGGER.error("IOException ", e);
}
}
if(bufferedWriter != null)
{
try {
bufferedWriter.close();
} catch (IOException e) {
LOGGER.error("IOException ", e);
}
}
}
}
}
Consume using:
StreamConsumer errorStreamConsumer = new StreamConsumer(proc.getErrorStream(),"errorfilepath");
StreamConsumer outputStreamConsumer = new StreamConsumer(proc.getInputStream(),"outputFilepath");
Doing the above will make sure the child process never hangs and is effectively monitored by the parent process.
See Also:
Process.waitFor(), threads, and InputStreams
http://www.javaworld.com/article/2071275/core-javahen-runtime-exec---won-t/core-java/when-runtime-exec---won-t.html
To acheive the second, the parent process needs to wait for the child process to complete its execution:
proc.waitFor();
causes the current thread to wait, if necessary, until the process
represented by this Process object has terminated. This method returns
immediately if the subprocess has already terminated. If the
subprocess has not yet terminated, the calling thread will be blocked
until the subprocess exits.
this is mandatory before you ask for the child process return code.
int returncode = proc.exitValue();