Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Runtime.getRuntime().exec(...) causes deadlock

We're trying to call an external program in Windows using Runtime.getRuntime().exec(...), but it seems to cause a deadlock. The external process is started asynchronously, but after a short while stops doing anything. When I stop the Java thread, the external process continues, so it must somehow be waiting for the Java thread. This is our relevant code at the moment:

try {
    Process process = Runtime.getRuntime().exec(System.getProperty("user.dir") + "program.exe");
    BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream())); //Read output of program from its buffer.
    String line;
    while((line = input.readLine()) != null) {
        System.out.println(line);
    }
    process.waitFor();
} catch(IOException e) {
    e.printStackTrace();
} catch(InterruptedException e) {
    e.printStackTrace();
}

The program stops after having output 3313 bytes. We tried various methods of emptying the buffer, since that seems to sometimes cause this problem.

The Java program is waiting for the external program to complete (process.waitFor()), and the external program doesn't complete until I terminate the Java program, hence causing a deadlock. How can we prevent this? We have no access to the source of the external program.

like image 459
Ghostkeeper Avatar asked Jul 13 '26 13:07

Ghostkeeper


1 Answers

Finally found the culprit. Apparently, the runtime process not only provides an input stream (Process#getInputStream), but also an error stream (Process#getErrorStream). The error stream was filling up as well, since the external program gave some errors about files being in the wrong format.

The solution consisted of making a new runnable class that reads from a stream in a separate thread. The the main thread would then create two instances of this object, one that will read from the input stream and the other from the error stream, then let both instances run their thread asynchronously. This way both streams were being read at the same time, and the main thread would call Process#waitFor.

I hope this helps someone who stumbles on this problem as well.

like image 117
Ghostkeeper Avatar answered Jul 16 '26 06:07

Ghostkeeper