2017-10-07 21 views
0

나는 웹을 이미 검색했으며, 질문은 process.waitFor() never returns으로 표시되어 stdout 또는 stderr이 읽지 않는 프로세스에서 종종 문제가 있음을 나타냅니다.Process.waitFor stdout과 stderr이 읽히더라도 응답하지 않는다

우리는 이것을 달성하기 위해 redirectOutputredirectErrorProcessBuilder를 사용하고, 나는 우리가 우리가 프로세스를 실행하는 데 사용할 다음과 같은 방법을 참조하십시오 안전을해야한다고 생각 : 아직

public static void execute(String directory, long timeout, File out, File err, String... command) throws InterruptedException, IOException { 
    LOGGER.log(Level.INFO, String.format("executing command %s (%s)", Arrays.toString(command), timeout > 0 ? String.format("timeout = %,d[ms]", timeout) : "no timeout")); 
    ProcessBuilder builder = new ProcessBuilder(); 
    builder.directory(new File(directory)); 
    builder.command(command); 
    builder.redirectOutput(out); 
    if(out == err) { 
     builder.redirectErrorStream(true);   
    } else { 
     builder.redirectError(err); 
    } 
    long time = System.currentTimeMillis(); 
    Process process = builder.start(); 
    try { 
     LOGGER.log(Level.FINE, "waiting for process"); 
     boolean exited = process.waitFor(timeout, TimeUnit.MILLISECONDS); 
     if(!exited) { 
      LOGGER.log(Level.WARNING, "timeout reached, trying to destroy ..."); 
      exited = destroy(silent, process); // Helper method to destroy processes 
     } 
     long duration = System.currentTimeMillis() - time; 
     int exitValue = process.exitValue(); 
     LOGGER.log(Level.INFO, "execution finished in " + duration + "[ms] => " + exitValue); 
    } catch (InterruptedException | Error | RuntimeException e) { 
     LOGGER.log(Level.SEVERE, "execution failed", e); 
     throw e; 
    } 
} 

를 문제가 있다는 것입니다 프로세스가 시간 초과 내에서 쉽게 끝났음에도 불구하고 process.waitFor(timeout, TimeUnit.MILLISECONDS) 호출에 응답하지 않습니다.

로깅 출력된다

Oct 07, 2017 12:39:55 AM at.ProcessExecutor execute 
INFO: executing command [java, -Xmx8G, -XX:+UseG1GC, -XX:+CrashOnOutOfMemoryError, -jar, MetricCalc.jar] (timeout = 14,400,000[ms]) 
Oct 07, 2017 12:39:55 AM at.ProcessExecutor execute 
FINE: waiting for process 

err 파일

... Things we write to std.err ... 
Finished Metrics 

를 판독 MetricCalc의 주요 방법

같다 (단 execution finished 라인이 아직 기록되지 않은 것을 인식)
public static void main(String[] args) { 
    .... do some stuff ... 
    System.err.println("Finished Metrics"); 
} 

읽기가 제대로 작동 함을 나타내면 Java 프로그램의 마지막 행이 실행되고 프로세스가 종료되어야합니다.

프로세스가 종료되지 않는 이유를 알고있는 사람은 누구나 Process.waitFor()에 계속 응답합니까?

+1

* ".... 프로세스가 종료되어야합니다."* - 하위 프로세스가 예상대로 작동한다고 가정합니다. 자식 프로세스가 실제로 종료되었는지 확인하십시오. 예 : "ps -efl"또는 유사한 것을 사용하십시오. –

+0

@StephenC : 나는 아직도'ps -efl | grep "java -Xmx8G"', 종료되지 않았 음을 나타냅니다. 그러나 MetricCalc (프로세스로 실행되는 Java 프로그램) 코드의 마지막 줄이 실행 된 이후로 이것이 왜 그런지는 잘 모릅니다 ... –

+1

오, 그냥 내 마음에 왔을 것입니다 : 아마도 MetricCalc 비 데몬 (non-deamon) 쓰레드가 실행 중이다. 이로 인해 애플리케이션이 종료되는 것을 막을 수있다. –

답변

0

Process.waitFor()에 문제가 아니었지만 프로세스가 종료되는 데 문제가있었습니다.

시작된 Java 응용 프로그램은 정확하게 shotdown을 얻지 못했던 ExecutorService을 사용했으며 좀비 스레드가 생존하여 프로세스가 종료되지 않았습니다.

executorService.shutdown()을 추가하면 문제가 해결되고 응용 프로그램이 예상대로 종료됩니다.