2009-10-29 4 views
2

Я использую класс ProcessBuilder Java для запуска внешнего процесса. Процесс не должен заканчиваться до выполнения программы Java; он должен оставаться в режиме командной строки/ответа.Java ProcessBuilder: внешний процесс зависает

Я знаю, что потоки процесса могут легко «заклинивать», если пренебречь, поэтому я сделал следующее: Программа считывает объединенные потоки вывода и ошибок процесса в потоке «читателя» и использует «писатель», для управления командами. Поток читателя блокирует чтение символов из выходного процесса, буферизует их в строки и отправляет результаты. Поток писателя записывает полные «командные» строки через PrintWriter; он использует очередь, чтобы гарантировать, что никакие две команды не будут «слишком близко друг к другу» (в настоящее время 100 мс), и что никакая новая команда не будет записана до завершения предыдущей команды. Я также называю flush() и checkError() после каждого println().

Эта схема работает нормально в течение нескольких секунд или минут, затем нить считывателя зависает при блокировке read(). Никаких ошибок, исключений не было, больше нет выходных данных процесса. После этого ничто не оживит внешний процесс (не дожидаясь его перезапуска). (BTW это происходит как на Linux, так и на Windows.)

Я просмотрел код и тестовые чеки в Jakarta Commons Exec и в Plexus Utils http://plexus.codehaus.org/plexus-utils/, но (a) не дает примера использования долгоживущего процесса и (б) ни одна из них не делает ничего принципиально отличного от того, что я описал.

Кто-нибудь знает, что здесь происходит, пожалуйста? Спасибо!

ответ

1

У вас также есть поток, управляющий stderr? Вы упомянули только о двух потоках.

+0

я называю processBuilder.redirectErrorStream (истина); перед processBuilder.start(). Так что должен быть только один комбинированный выходной поток. – 2009-10-29 13:03:06

+0

Вы используете отладчик? Если это так, то показывается, какие потоки принадлежат/хотят мьютексы, такие как eclipse? Похоже, это может быть тупик. – Benj

+0

Да, я отлаживал его в Eclipse, но основное приложение работает довольно успешно - он просто ничего не может сделать полезным, пока читатель не вернет некоторые данные. – 2009-10-29 13:13:33

0

Просто догадаться, но вы попытались объединить ошибки и выходные потоки?

+0

Нет, у меня нет, и я попробую это дальше, но я не слишком оптимистичен. Если redirectErrorStream не работает, это ошибка в ProcessBuilder. И я действительно вижу некоторый вывод stderr в моем объединенном потоке, прежде чем он умрет. – 2009-10-29 13:06:17

+0

OK Я попытался разделить потоки, и поток ошибок обрабатывается собственным потоком. Никаких изменений в поведении stdout, хотя ... – 2009-10-29 13:47:09

1

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

Я тестировал как на windows/linux множество встроенных приложений cmd/bash, так и других двоичных файлов cmd, и он отлично работает, за исключением случаев, когда он просто бросает исключение IO-потока, что я делаю - это исключение и исключение снова перезапустите поток, чтобы программа продолжала работать.

Если вы пытаетесь использовать ssh в linux, вы можете столкнуться с проблемой, так как вы не сможете писать на тот же stdin, это из соображений безопасности.

Попробуйте принимать входные данные от System.in и посмотреть, если он работает, он работал в моем случае

Смежные вопросы