简体   繁体   中英

Why can't my Java program read Perl's STDERR?

We have a Perl program to validate XML which is invoked from a Java program. It is not able to write to standard error and hanging in the print location.

Perl is writing to STDERR and a java program is reading the STDERR using getErrorStream() function. But the Perl program is hanging to write to STDERR. I suspect Java function is blocking the STDERR stream completely and Perl is waiting for this stream to be released.

Is there a way in Perl to overcome this blockage and write to standard error forcefully? Since Java is doing only a read the API should not be locking the STDERR stream as per java doc.

Perl Code snippet is:

sub print_error
{
    print STDERR shift;
}

Java code snippet is:

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

Appreciate the help in advance.

Thanks, Mathew Liju

getErrorStream does not read the error stream, it just obtains a handle to it. As it's a pipe, if you never actually read it, it will fill up and force the Perl program to block.

You need something like:

Inputstream errors = getErrorStream();
while (errors.read(buffer) > 0) {
    SOP buffer;
}

An additional factor to consider is the buffering that occurs with piped processes.

There is by default, about a 30-line-ish buffer that is maintained by the shell creating the inter-process pipe, so if the Perl app has not created enough data, it won't have been sent to the Java application yet to process.

May be this thread has a possible cause for your problem:

Add 3 lines to the top of the Perl script:

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

The problem in the mentioned thread was related to "the way Perl is buffering its output".

However here, Adrian Pronk mentions in the comments that "Perl is hanging because Java is never reading its output".

Ideally, I think that to avoid deadlock, in Java you need to spawn separate threads to read the STDERR and the STDOUT. It sounds like Perl is blocking when writing to STDERR because for one reason or another you are never reading from it in Java.

STDOUT->autoflush(1);
STDERR->autoflush(1);

This is the information I needed! I have a Java app running some Perl scripts and I'd only get the output after it was finished. By adding the autoflush(1) I get it right away.

BTW, I do have separate threads for reading STDERR and STDOUT , and that's the way to go.

Thanks.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM