Search code examples
javaprocessbuilderlinphone

Application stops responding when using Process.waitFor()


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);
    }

}

enter image description here


Solution

  • 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);