2016-04-11 9 views
1

У меня есть процесс, который запускается через Spring JMSListener. Процесс в основном запускает exe Runtime, чтобы вызвать imagemagick, чтобы выполнить некоторую переработку изображения. В разделе * nix существуют потоки, которые остаются, несмотря на то, что команда exec Runtime завершает работу с кодом завершения 0 и никаких исключений не выбрасывается. Приложение использует класс Gythio Runtime Exec для выполнения своей работы. Не выдерживая обычных ловушек вокруг StdErr и StdOut, которые могут возникнуть с Runtime, с которыми Gythio правильно справляется, не следует ли нам уничтожить этот процесс, даже если он был успешным?Должен ли я вызвать Process.destroy(), если процесс завершается кодом завершения 0?

Вот простой пример, пожалуйста, игнорируйте ошибки кода, которые не предназначены для реального кода. Мой вопрос вокруг // процесс сделал блок:

public class Test { 

    public void doSomething(String cmd, String processProperties, String processDirectory){ 

     try { 
      // cmd is something like convert ... file .. params 

      Runtime runtime = Runtime.getRuntime(); 

      final Process process = runtime.exec(cmd, processProperties, processDirectory); 

      int exitValue = process.waitFor(); 

      System.out.println("exit value: " + exitValue); 
      BufferedReader buf = new BufferedReader(new InputStreamReader(
        process.getInputStream())); 
      String line = ""; 
      while ((line = buf.readLine()) != null) { 
       System.out.println("exec response: " + line); 
       //log = line; 
       //writeToFile(line); 
      } 
      // process is done... should it be destroyed? 
      if(process != null){ 
       process.destroy(); 
      } 
      // end process done 
     } catch (Exception e) { 
      System.out.println(e); 
     } 
    } 
} 

Примерно через час бега, приложение, запущенное в коте показывает эти темы (где кот является PID 1641):

[[email protected] logs]# top -H -p 1641 
top - 19:45:24 up 264 days, 10:33,  4 users,  load average: 0.00, 0.00, 0.19 
Tasks: 5068 total,   0 running, 5068 sleeping,   0 stopped,   0 zombie 
Cpu(s):  0.7%us,  1.5%sy,  0.0%ni, 97.8%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st 
Mem:   8061332k total,  6690912k used,  1370420k free,   195348k buffers 
Swap:  1888252k total,    77672k used,  1810580k free,  5070148k cached 

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND 
1734 adminuser  20   0 5842m 948m  13m S  0.3 12.0   3:03.41 java 
1641 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:00.00 java 
1643 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:01.20 java 
1644 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:02.31 java 
1671 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:02.28 java 
1678 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:02.35 java 
1686 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:02.20 java 
1687 adminuser  20   0 5842m 948m  13m S  0.0 12.0   2:25.66 java 
1688 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:00.11 java 
1691 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:00.08 java 
1706 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:00.00 java 
1712 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:53.24 java 
1720 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:39.38 java 
1721 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:12.96 java 
1722 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:00.00 java 
1723 adminuser  20   0 5842m 948m  13m S  0.0 12.0   2:54.47 java 
1724 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:00.00 java 
1728 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:03.62 java 
1729 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:08.16 java 
1731 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:00.75 java 
1732 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:02.58 java 
1735 adminuser  20   0 5842m 948m  13m S  0.0 12.0   3:03.63 java 
1736 adminuser  20   0 5842m 948m  13m S  0.0 12.0   3:02.23 java 
1737 adminuser  20   0 5842m 948m  13m S  0.0 12.0   3:00.92 java 
1738 adminuser  20   0 5842m 948m  13m S  0.0 12.0   3:03.59 java 
1739 adminuser  20   0 5842m 948m  13m S  0.0 12.0   3:02.96 java 
1740 adminuser  20   0 5842m 948m  13m S  0.0 12.0   3:05.07 java 
1741 adminuser  20   0 5842m 948m  13m S  0.0 12.0   3:02.26 java 
1742 adminuser  20   0 5842m 948m  13m S  0.0 12.0   3:04.57 java 
1743 adminuser  20   0 5842m 948m  13m S  0.0 12.0   3:01.79 java 
1744 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:26.27 java 
1745 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:00.10 java 
1746 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:10.72 java 
1747 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:00.00 java 
1748 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:10.99 java 
5611 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:00.68 java 
5620 adminuser  20   0 5842m 948m  13m S  0.0 12.0   0:00.36 java 

Любого/все ответы приветствуются! Заранее спасибо!

+1

Очищены ли они, если вы закрываете поток (например, используя ресурсы try-with-resources)? –

+1

Вы не думаете, что это необходимо. Вы могли бы подумать, что если процесс вернул код выхода, который он вызвал 'exit()' или вернулся из main, поэтому нет процесса для уничтожения. – EJP

+0

Программа не может выйти (или вернуть код выхода), пока она не закончится и программа не будет закрыта. –

ответ

0

Я подозреваю, что ваша программа создает нетривиальный выход. Когда вы запустите программу в фоновом режиме, она напишет размер буфера, который может быть всего несколькими килобайтами. Как только размер буфера достигнут, дождитесь, пока потребитель, ваша программа, прочитает результат. Это относится к стандартным ошибкам и ошибкам.

Если вы не потребляете выходные данные и ошибки, ваша нерешенная программа может ждать вечно, но вы ожидаете сначала кода выхода, которого не будет, поэтому вы получите тупик.

Я предлагаю вам использовать ProcessBuilder, перенаправить ошибку на выход и прочитать оба конца до того, как ожидает код выхода.

Из примера.

ProcessBuilder pb = new ProcessBuilder("myCommand", "myArg1", "myArg2"); 
pb.redirectErrorStream(true); 
File log = new File("log"); 
pb.redirectOutput(Redirect.appendTo(log)); 
Process p = pb.start(); 
// no need to copy the output 
int exit = p.waitFor(); 
+0

Пример был просто для иллюстрации того, где я думал, что класс https://github.com/Alfresco/gytheio/blob/master/gytheio-commons/src/main/java/org/gytheio/util/exec/RuntimeExec.java может нужен процесс process.destroy(). Если вы посмотрите на класс, lib потребляет std-выход и ошибки, поэтому я не думаю, что это так. Я склонен согласиться с комментариями, приведенными выше @EJP. Спасибо хоть! – Griff

+0

@Griff этот код очень отличается от кода в вашем вопросе. –