使用ProcessBuilder执行进程会导致waitFor挂起

时间:2012-08-01 09:21:56

标签: java exec

我在使用Java运行exernal应用程序时遇到问题。我知道输入和输出流的问题,我正在尝试按如下方式阅读它们:

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

我正在执行的命令是一个URL的xdg-open,所以它不应该等待输入。

这在我的机器上有十分之九的作品,但有时它只是挂在pb.start();并且不执行该命令。

java线程正在等待进程返回。这是堆栈跟踪:

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)

以下是strace告诉我的事情:

$ sudo strace -p 13255
Process 13255 attached - interrupt to quit
futex(0x7fbb673e49d0, FUTEX_WAIT, 13262, NULL

1 个答案:

答案 0 :(得分:0)

我们在CentOS 6.3 JDK 1.6.0_33-b03上也观察到了这样的问题。 调查显示,在此Java进程中发生OutOfMemoryError之后会发生这种情况。

查看类java.lang.UNIXProcess的代码我想,当在UNIXProcess构造函数中的单独线程运行中抛出非IO异常(例如,错误)时,可能会发生此类问题,位于第109行和第130行之间这段代码更好地组织为

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

,但它被组织为

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

,因此非IO异常可能导致不调用gate.exit(),导致主调用程序线程在方法gate.waitForExit()(第145行)中永远挂起的原因。

相关问题