2

I have a problem in my code

ProcessBuilder pb = new ProcessBuilder("my program.exe","-g");
Process core = pb.start();
if(!core.waitFor(5, TimeUnit.HOURS))
{
    isDestroyed = true;
    core.destroy();
}
else
    isDestroyed = false;

String xmlOutput = IOUtils.toString(core.getInputStream());

And the problem is that it works all the time exactly 5 hours, but when I run it from console, it works <10 seconds. What's the problem? OS is Windows 8.1 64bit.

I want it runs the same time as from console. Or there is another good way to get output? If yes, please say how. Thanks

ivan
  • 287
  • 3
  • 14
  • Do you have a requirement of waiting for 5 hours or you just need to wait till the Process completes? – m3nation Jun 09 '15 at 07:18
  • See [Java ProcessBuilder: Resultant Process Hangs](http://stackoverflow.com/questions/3285408/java-processbuilder-resultant-process-hangs). –  Jun 09 '15 at 07:21
  • @m3nation, process should work not more than 5 hours – ivan Jun 09 '15 at 07:24
  • Check this link: [time limit for Process.waitFor](http://stackoverflow.com/questions/8887053/time-limit-for-process-waitfor) my friend. – m3nation Jun 09 '15 at 07:33

3 Answers3

1

You can have your process return its output while it's processing:

ProcessBuilder pb = new ProcessBuilder("my program.exe","-g");
Process core = pb.start();
InputStream stream = core.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
String line;
StringBuilder stringBuilder = new StringBuilder();
long end = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(5);

while (System.currentTimeMillis() < end && (line = reader.readLine()) != null) {
    stringBuilder.append(line);
}
stream.close();
String xmlOutput = stringBuilder.toString();
  • It should be limited 5 hours. If I add the lines: `long end = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(5);` and the condition into the cycle `while (System.currentTimeMillis() < end && (line = reader.readLine()) != null)` will that work correctly? – ivan Jun 09 '15 at 07:40
  • @ivan Indeed, that would stop the process after five hours, unless finished earlier. – Hummeling Engineering BV Jun 09 '15 at 07:48
  • I'm trying to use this algorithm with `stderr` (viz., `InputStream stream = core.getErrorStream()`), but there's nothing coming from the `readLine`. Is that to be expected when there's no error or what am I doing wrong? – JohnK May 31 '22 at 21:03
  • @JohnK The `readLine()` method returns `null` when there's no errors. Does it do that? – Hummeling Engineering BV Jun 01 '22 at 14:53
  • @HummelingEngineeringBV Thanks for your reply! I wasn't getting anything *but* null. But I figured out my problem: I had set `.redirectError(ProcessBuilder.Redirect.INHERIT)` on the ProcessBuilder and forgetten about it. Thanks again for your reply! – JohnK Jun 01 '22 at 18:18
0

You're deadlocked for 5 hours waiting for the process to exit while it is waiting for you to consume some input so it won't be blocked producing it so it can exit.

You should consume the input first, and then do the waitFor().

NB You also need to close the output stream to the process so it isn't waiting for input.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • My program is a scanner that can work very huge time. But I want to limit this 5 hours. Will that work? I mean that reading can take more than 5 hours, I worry about it – ivan Jun 09 '15 at 07:37
0

Consume the process's STDOUT in another thread. And main thread waits for the process terminattion.

    ProcessBuilder pb = new ProcessBuilder("my program.exe","-g");
    Process core = pb.start();
    InputStream stream = core.getInputStream();
    BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
    StringBuilder stringBuilder = new StringBuilder();
    new Thread(() -> {
        try {
            String line;
            while ((line = reader.readLine()) != null) {
                stringBuilder.append(line);
            }
        } catch (IOException ex) {
        }
    }).start();;
    if(!core.waitFor(5, TimeUnit.HOURS)) {
        isDestroyed = true;
        core.destroy();
    } else
        isDestroyed = false;