2016-04-11 2 views
1

J'ai un processus démarré via un Spring JMSListener. Le processus exécute essentiellement un exe Runtime pour appeler imagemagick pour faire un retraitement d'une image. Sous * nix, il y a des threads qui restent même si la commande exec Runtime se termine avec le code de sortie 0 et aucune exception n'est levée. L'application utilise la classe Gythio Runtime Exec pour effectuer son travail. Nonobstant les pièges habituels autour de StdErr et StdOut qui peuvent survenir avec Runtime, que Gythio gère correctement, ne devrions-nous pas détruire le processus même s'il a réussi?Dois-je appeler Process.destroy() si le processus se termine par le code de sortie 0?

Voici un exemple simple, s'il vous plaît ignorer les erreurs de code son pas destiné à être du code réel. Ma question est autour du processus // fait bloc:

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

Après environ une heure de course, l'application en cours d'exécution dans tomcat montre ces fils (où tomcat est 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 

Tous/toutes les réponses sont appréciées! Merci d'avance!

+1

Sont-ils nettoyés si vous fermez le flux (par exemple en utilisant un essai avec-ressources)? –

+1

Vous ne penseriez pas que cela devrait être nécessaire. On pourrait penser que si le processus a retourné un code de sortie, il a appelé 'exit()' ou est retourné hors de main, donc il n'y a pas de processus à détruire. – EJP

+0

Un programme ne peut pas quitter (ou renvoyer un code de sortie) jusqu'à la fin et la fermeture du programme. –

Répondre

0

Je suppose que votre programme crée une sortie non triviale. Lorsque vous exécutez un programme en arrière-plan, il écrira la taille de la mémoire tampon qui pourrait être juste quelques Ko. Une fois la taille du tampon atteinte, attendez que le consommateur, votre programme, lise la sortie. Ceci s'applique à la sortie standard et à l'erreur. Si vous ne consommez pas la sortie et l'erreur, votre programme engendré peut attendre indéfiniment, mais vous attendez le code de sortie en premier ce qui n'arrivera pas, de sorte que vous obtenez un blocage.

Je vous suggère d'utiliser ProcessBuilder, de rediriger l'erreur vers la sortie et de lire les deux à la fin avant d'attendre le code de sortie.

De l'exemple.

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

L'exemple était simplement pour illustrer où je pensais que la classe https://github.com/Alfresco/gytheio/blob/master/gytheio-commons/src/main/java/org/gytheio/util/exec/RuntimeExec.java ont eu besoin d'un process.destroy(). Si vous regardez la classe, la lib consomme la sortie standard et les erreurs, donc je ne pense pas que c'est ça. J'ai tendance à être d'accord avec les commentaires ci-dessus par @EJP. Merci quand même! – Griff

+0

@Griff ce code est très différent de celui de votre question. –