2

I'm having problems with running an exernal application out of Java. I'm aware of the problem with the input and output streams, and I'm trying to read them as follows:

    ProcessBuilder pb = new ProcessBuilder(args);
    args[args.length - 1] += "<NUL";

    pb.redirectErrorStream(true);
    Process p = pb.start();

    InputStreamReader isr = new InputStreamReader(p.getInputStream());
    BufferedReader input = new BufferedReader(isr);
    while (input.readLine() != null) {
    }       

    p.waitFor();
    input.close();
    isr.close();

The command I'm executing is xdg-open for an URL, so it shouldn't wait for input.

This works nine times out of ten on my machine, but sometimes it simply hangs at pb.start(); and the command isn't executed.

The java thread is waiting on the process to return. Here's the stack trace:

Name: LinkHandlerExec
State: WAITING on java.lang.UNIXProcess$Gate@356122dc
Total blocked: 0  Total waited: 1

Stack trace: 
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:502)
java.lang.UNIXProcess$Gate.waitForExit(UNIXProcess.java:80)
java.lang.UNIXProcess.<init>(UNIXProcess.java:161)
java.lang.ProcessImpl.start(ProcessImpl.java:81)
java.lang.ProcessBuilder.start(ProcessBuilder.java:468)

Here's what strace tells me:

$ sudo strace -p 13255
Process 13255 attached - interrupt to quit
futex(0x7fbb673e49d0, FUTEX_WAIT, 13262, NULL
alexsb
  • 548
  • 4
  • 17
  • Is this related?: http://stackoverflow.com/questions/1043611/failure-to-start-program-from-java-using-processbuilder?rq=1 – Baz Aug 01 '12 at 09:25
  • while (input.readLine() != null) {} // empty while is this like this only in your original code – Harmeet Singh Aug 01 '12 at 09:25
  • http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=2 – LiuYan 刘研 Aug 01 '12 at 09:40
  • @Baz, yes, it's related. I've tried moving the closing of the strims after the wait, as suggested there, but that didn't have an effect. – alexsb Aug 01 '12 at 09:46
  • @LiuYan - I've read the Java World Article and am aware of the problems. The code there is from 2000 and ProcessBuilder is a better choice in my opinion. I've tried it to, but had similar problems – alexsb Aug 01 '12 at 09:46
  • Try reading the error stream as well – MadProgrammer Aug 01 '12 at 10:25
  • pb.redirectErrorStream(true); should take care of that – alexsb Aug 01 '12 at 10:41
  • Can you confirm that it hangs at `p.waitFor()`, not at `input.readLine()`? And, print the result of `input.readLine()` may help debugging. – LiuYan 刘研 Aug 01 '12 at 11:33
  • I checked again, and it does not hang at waitFor() (I corrected that in the original answer) but at pb.start(); Thanks for the hint! There is nothing read in any situation, but it never geht's there when it hangs. – alexsb Aug 01 '12 at 11:42
  • What OS are you on? If you are on linux, you might want to use `strace` to see what syscalls the processes are currently executing. Might or might not be helpful, but worth a try. – MvG Aug 01 '12 at 12:04
  • Thanks @MvG I'm on linux. The output seems to not be very helpful: $ sudo strace -p 13255 [sudo] password for alexsb: Process 13255 attached - interrupt to quit futex(0x7fbb673e49d0, FUTEX_WAIT, 13262, NULL – alexsb Aug 01 '12 at 15:46
  • @alexsb, I feared that futex thing might happen. But what about the child process? Has that started yet, and if so, where is it blocked? – MvG Aug 01 '12 at 18:26

1 Answers1

0

We also observed such problem on CentOS 6.3 JDK 1.6.0_33-b03. Investigation showed that this happens after OutOfMemoryError has happened in this Java process.

Looking to the code of class java.lang.UNIXProcess I suppose that such problem may happen when a non-IO Exception (e.g. an Error) gets thrown in the separate thread run within the UNIXProcess constructor, somewhere between lines 109 and 130. This code would better be organized as

try {
  .....
} finally {
  gate.exit();
}

, but instead it is organized as

try {
  ...
} catch (IOException e) {
  gate.setException(e); /*remember to rethrow later*/
  gate.exit();
  return;
}
...
gate.exit(); 

, so a non-IO exception may cause gate.exit() not to be called, what causes the main caller thread to hang up forever in method gate.waitForExit() (line 145).