Question

Working on SEAndroid, I call Setools commands from my Java application. It works perfectly with small SEAndroid policy and now I need to test my tool with real SEAndroid policy. But unfortunately, I face a problem with an error stream.

Here my code I used to call external commands :

public static BufferedReader runCommand(final String[] args)
            throws IOException {

    BufferedReader stdInput = null;
    BufferedReader stdError = null;
    try {
        Process p = Runtime.getRuntime().exec(args);

        stdInput = new BufferedReader(new
                InputStreamReader(p.getInputStream()));

        stdError = new BufferedReader(new
                InputStreamReader(p.getErrorStream()));

        // read any errors from the attempted command
        String s = null;
        StringBuilder err = new StringBuilder();

        while ((s = stdError.readLine()) != null) {
            err.append(s + "\n");
        }
        if (err.length() != 0) {
            throw new IOException(err.toString());
        }

        return stdInput;
    } finally {
        if (stdError != null) {
            stdError.close();
        }
    }
}

So, as you can see, I call an external command. Then read the error stream and throw an exception if there is any errors, otherwise I return the InputStream, so I can parse it later.

With a real SEAndroid policy, the error stream seems to block (even if I read a single char) and I can't parse the result of the command. If I close the error stream without reading anything, the application works fine, but I want to handle errors if any. If I type the command in a console, it works fine too.

In the first case (with small SEAndroid policy), the output of the command is small ( ~350 lines). In the second case (with a real SEAndroid policy), the output of the command is larger ( >1500 lines).

Is it possible that the size of the output stream influences the error stream? The two streams are two distinctive resources, isn't it? The fact that I do not read the output stream immediately have an importance?

I fear that its not a "programming" problem but more a system problem...

Any suggestion?

Thanks in advance for your help=)

Edit:

I try to read the output stream before the error stream and it works. But I need to check the error stream before perform any parsing on the output stream, so the problem is still topical.

Was it helpful?

Solution

First, it's probably better to use the newer ProcessBuilder class as opposed to Runtime exec. If you want to go a step further, you can even use Apache commons-exec which takes care of stream handling and other things for you.

Next, as you've discovered, process control is a tricky thing in Java and you've run into one of its tricky issues. From the documentation for java's Process class:

The parent process uses these streams to feed input to and get output from the subprocess. Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.

You need to have something consuming both (Error and Output) streams or you risk deadlock - these should each be read on their own threads. Using something like a StreamGobbler (google it, there are plenty out there) would be a good step, or you can roll your own if you're so inclined. It isn't too hard to get it right but if you're unfamiliar with multithreading you may want to look at someone else's implementation or go the Apache commons-exec route.

OTHER TIPS

The processing of output is so annoying, that I wrote little library called jproc that deals with the problem of consuming stdout and stderr. It can simply filter strings through external programs likes this:

ProcBuilder.filter("x y z","sed" ,"s/y/a/")

It also lets you specify a timeout for the completion and will convert non-zero exit codes into exception.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top