tags:

views:

689

answers:

5

Hi,

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

+4  A: 

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.

Kent Fredric
+4  A: 

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".

VonC
Perl won't hang because of buffering unless it is expecting Java to reply. With buffering, Java will see the output eventually, even if it is only when Perl exits. Perl is hanging because Java is never reading its output
Adrian Pronk
+8  A: 

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;
}
Adrian Pronk
+4  A: 

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.

skiphoppy
A: 

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.

Robert