Почему моя Java-программа не может прочитать STDERR в Perl? - PullRequest
5 голосов
/ 10 декабря 2008

У нас есть Perl-программа для проверки XML, которая вызывается из Java-программы. Он не умеет писать со стандартной ошибкой и зависает в месте печати.

Perl пишет в STDERR, а Java-программа читает STDERR с помощью функции getErrorStream (). Но программа Perl зависает, чтобы написать в STDERR. Я подозреваю, что функция Java полностью блокирует поток STDERR, и Perl ожидает освобождения этого потока.

Есть ли в Perl способ преодолеть эту блокировку и принудительно записать в стандартную ошибку? Поскольку Java выполняет только чтение, API не должен блокировать поток STDERR согласно документу Java.

Фрагмент кода Perl:

sub print_error
{
    print STDERR shift;
}

Фрагмент кода Java:

while ( getErrorStream() != null )
{
    SOP errorMessage;
}

Заранее признателен за помощь.

Спасибо, Мэтью Лию

Ответы [ 5 ]

7 голосов
/ 10 декабря 2008

getErrorStream не читает поток ошибок, он просто получает дескриптор к нему. Так как это канал, если вы никогда его не прочитаете, он заполнится и заставит программу Perl блокироваться.

Вам нужно что-то вроде:

Inputstream errors = getErrorStream();
while (errors.read(buffer) > 0) {
    SOP buffer;
}
4 голосов
/ 10 декабря 2008

В идеале, я думаю, что во избежание тупиковой ситуации в Java нужно создавать отдельные потоки для чтения STDERR и STDOUT. Похоже, что Perl блокирует при записи в STDERR, потому что по той или иной причине вы никогда не читаете из него на Java.

4 голосов
/ 10 декабря 2008

Может быть эта тема имеет возможную причину вашей проблемы:

Добавьте 3 строки в начало скрипта Perl:

use IO::Handle;
STDOUT->autoflush(1);
STDERR->autoflush(1);

Проблема в упомянутом потоке была связана с тем, "как Perl буферизирует свой вывод".

Однако здесь, Адриан Пронк упоминает в комментариях, что "Perl зависает, потому что Java никогда не читает свой вывод".

4 голосов
/ 10 декабря 2008

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

По умолчанию существует примерно 30-строчный буфер, который поддерживается оболочкой, создающей межпроцессный канал, поэтому, если приложение Perl не создало достаточно данных, оно не будет отправлено на Java заявка еще не обработана.

0 голосов
/ 24 ноября 2009
STDOUT->autoflush(1);
STDERR->autoflush(1);

Это информация, которая мне была нужна! У меня есть приложение Java, выполняющее некоторые сценарии Perl, и я получу вывод только после его завершения. Добавив autoflush(1), я сразу понял.

Кстати, у меня есть отдельные темы для чтения STDERR и STDOUT, и это путь.

Спасибо.

...