Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading error stream from a process

I am writing a java program to read the error stream from a process . Below is the structure of my code --

ProcessBuilder probuilder = new ProcessBuilder( command );              
Process process = probuilder.start(); 
InputStream error = process.getErrorStream();
InputStreamReader isrerror = new InputStreamReader(error);
BufferedReader bre = new BufferedReader(isrerror);
while ((linee = bre.readLine()) != null) {
        System.out.println(linee);
    }

The above code works fine if anything is actually written to the error stream of the invoked process. However, if anything is not written to the error stream, then the call to readLine actually hangs indefinitely. However, I want to make my code generic so that it works for all scenarios. How can I modify my code to achieve the same.

Regards, Dev

like image 917
user496934 Avatar asked Oct 16 '12 06:10

user496934


2 Answers

readline() is a blocking call. It will block until there's a line to be read (terminated by an end of line character) or the underlying stream is closed (returning EOF).

You need to have logic that is checking BufferedReader.ready() or just using BufferedReader.read() and bailing out if you decide you're waiting long enough (or want to do something else then check again).

Edit to add: That being said, it shouldn't hang "indefinitely" as-is; it should return once the invoked process terminates. By any chance is your invoked process also outputting something to stdout? If that's the case ... you need to be reading from that as well or the buffer will fill and will block the external process which will prevent it from exiting which ... leads to your problem.

like image 108
Brian Roach Avatar answered Sep 27 '22 17:09

Brian Roach


This is a late reply, but the issue hasn't really solved and it's on the first page for some searches. I had the same issue, and BufferedReader.ready() would still set up a situation where it would lock.

The following workaround will not work if you need to get a persistent stream. However, if you're just running a program and waiting for it to close, this should be fine.

The workaround I'm using is to call ProcessBuilder.redirectError(File). Then I'd read the file and use that to present the error stream to the user. It worked fine, didn't lock. I did call Process.destroyForcibly() after Process.waitFor() but this is likely unnecessary.

Some pseudocode below:


    File thisFile = new File("somefile.ext");
    ProcessBuilder pb = new ProcessBuilder(yourStringList);
    pb.redirectError(thisFile);
    Process p = pb.start();
    p.waitFor();
    p.destroyForcibly();
    ArrayList fileContents = getFileContents(thisFile);

I hope this helps with at least some of your use cases.

like image 40
sarysa Avatar answered Sep 27 '22 17:09

sarysa