I'm launching an external application from within my Java application (8u11). However the application becomes non-responsive to UI input up under Windows XP and Windows 7 with the standard hour glass/spinner.
I've narrowed this problem down to whether or not I use Process.waitFor(). If I call it I see the problems, if I don't it works fine. Also the application un-freezes if I then quit the Java application.
My question is why is this the case - how can calling waitFor() possibly effect the internal runnings of a child process? And how can I avoid this problem?
The application in question is LinPhone.exe but I don't believe the issue is specific to the application - there must be some general way in which it handles standard IO etc which the way I'm interfering with by calling waitFor().
I need to use Process.waitFor() so I can track when the application has exited.
I've simplified the issue to this SCCEE.
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
public class LinphoneTest {
public static void main(String[] args) throws IOException,
InterruptedException {
String phoneAppPath = "C:\\Program Files\\Linphone\\bin\\linphone.exe";
ProcessBuilder processBuilder = new ProcessBuilder(phoneAppPath);
// move up from bin/linephone.exe
File workingDir = new File(phoneAppPath).getParentFile()
.getParentFile();
processBuilder.directory(workingDir);
processBuilder.redirectErrorStream();
Process process = processBuilder.start();
final BufferedReader stdout = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line = null;
try {
while (((line = stdout.readLine()) != null)) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
new Thread(() -> {
try {
process.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "process wait").start();
Thread.sleep(Long.MAX_VALUE);
}
}
To summarise discussion, I was not handling standard error streams causing linphone to lockup as its output buffer for standard error became full especially as linphone produces a lot of verbose output on standard error. When RunTime.exec wont provides excellent summary of the pitfalls involved in calling processes from Java.
There was also a typo, I was calling the non-standard named getter
processBuilder.redirectErrorStream();
when I should have been calling the "setter"
processBuilder.redirectErrorStream(true);