2009-10-29 5 views
2

J'utilise la classe ProcessBuilder de Java pour exécuter un processus externe. Le processus ne doit pas se terminer avant le programme Java; il doit rester vivant en mode de commande/réponse. Je sais que les flux de processus peuvent facilement être bloqués s'ils sont négligés, donc j'ai fait ce qui suit: Le programme lit les flux de sortie et d'erreur combinés du processus dans un fil "lecteur", et utilise un "scripteur" thread pour gérer les commandes. Le thread de lecture bloque les lectures de caractères à partir de la sortie du processus, les met en mémoire tampon dans les chaînes et distribue les résultats. Le thread d'écriture écrit des lignes "command" complètes via un PrintWriter; il utilise une file d'attente pour s'assurer qu'aucune écriture de commande n'est "trop ​​rapprochée" (actuellement 100ms), et qu'aucune nouvelle commande n'est écrite avant que la sortie de la commande précédente soit terminée. J'appelle aussi flush() et checkError() après chaque println().Java ProcessBuilder: le processus externe se bloque

Ce schéma fonctionne correctement pendant quelques secondes ou minutes, puis le thread de lecture se bloque sur le blocage read(). Pas d'erreurs, pas d'exceptions levées, plus de sortie de processus. Par la suite, rien ne relancera le processus externe (à moins de le redémarrer). J'ai examiné le code et les cas de test dans Jakarta Commons Exec et dans Plexus Utils http://plexus.codehaus.org/plexus-utils/ mais (a) ne donne aucun exemple d'utilisation d'un processus à longue durée de vie. et (b) aucun ne semble faire quelque chose de fondamentalement différent de ce que j'ai décrit.

Est-ce que quelqu'un a une idée de ce qui se passe ici s'il vous plaît? Merci!

Répondre

1

Avez-vous également une gestion de thread stderr? Vous ne mentionnez que les deux flux.

+0

J'appelle processBuilder.redirectErrorStream (true); avant processBuilder.start(). Donc, il ne devrait y avoir qu'un seul flux de sortie combiné. –

+0

Utilisez-vous un débogueur? Si oui, est-ce que cela supporte de montrer quels threads possèdent/veulent des mutex comme l'eclipse? On dirait que ça pourrait être une impasse. – Benj

+0

Oui, je l'ai débogué dans Eclipse, mais l'application principale continue de fonctionner assez bien - elle ne peut rien faire d'utile tant que le lecteur n'a pas retourné certaines données. –

0

Juste une supposition, mais avez-vous essayé de décompacter l'erreur et les flux de sortie?

+0

Non, je n'ai pas et je vais essayer ça, mais je ne suis pas trop optimiste. Si redirectErrorStream ne fonctionne pas, c'est un bug dans ProcessBuilder. Et je vois effectivement une sortie stderr sur mon flux combiné avant de mourir. –

+0

OK J'ai essayé de scinder les flux, et le flux d'erreur est géré par son propre thread. Pas de changement dans le comportement de stdout si ... –

1

J'ai implémenté des flux d'erreur, d'entrée et de sortie dans trois threads séparés et je peux lire et écrire sans problème des processus externes.

J'ai testé à la fois Windows/Linux avec une multitude d'applications intégrées cmd/bash ainsi que d'autres binaires de ligne cmd et ça fonctionne bien sauf à certaines occasions, il jette juste l'exception de flux, ce que je fais est attraper l'exception redémarrez le thread à nouveau, de sorte que le programme continue de fonctionner. Si vous essayez par exemple ssh dans linux, alors vous pourriez rencontrer des problèmes comme si vous ne pouviez pas écrire dans le même fichier stdin, ceci pour des raisons de sécurité.

Essayez de prendre l'entrée de System.in et voir si cela fonctionne, il a travaillé dans mon cas

Questions connexes