Java ProcessBuilder: внешний процесс зависает

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

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

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

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

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


person Community    schedule 29.10.2009    source источник


Ответы (3)


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

person Benj    schedule 29.10.2009
comment
Я вызываю processBuilder.redirectErrorStream (true); перед processBuilder.start (). ТАК должен быть только один комбинированный выходной поток. - person ; 29.10.2009
comment
Вы используете отладчик? Если да, поддерживает ли он отображение того, какие потоки владеют / хотят мьютексы, такие как eclipse? Похоже, это может быть тупик. - person Benj; 29.10.2009
comment
Да, я отлаживал его в Eclipse, но основное приложение продолжает работать нормально - оно просто не может делать ничего полезного, пока читатель не вернет некоторые данные. - person ; 29.10.2009

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

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

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

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

person Johnydep    schedule 07.12.2011

Просто предположение, но пробовали ли вы разделить потоки ошибок и вывода?

person flicken    schedule 29.10.2009
comment
Нет, я не пробовал, и в следующий раз попробую, но я не слишком оптимистичен. Если redirectErrorStream не работает, это ошибка в ProcessBuilder. И я действительно вижу некоторый вывод stderr в моем объединенном потоке, прежде чем он умрет. - person ; 29.10.2009
comment
Хорошо, я пробовал разделить потоки, и поток ошибок обрабатывается отдельным потоком. Однако никаких изменений в поведении stdout ... - person ; 29.10.2009