Alex Rivera | Logout

Runtime.exec() bug: hangs without providing a Process object

Asked 2011-12-31T13:30:39.627
18

Whether I use this:

process = Runtime.getRuntime().exec("logcat -d time");

or that:

process = new ProcessBuilder()
              .command("logcat", "-d", "time")
              .redirectErrorStream(true)
              .start();

I get the same results: it often hangs within the exec() or start() call, no matter what I tried to do! The thread running this cannot even be interrupted with Thread.interrupt()! The child process is definitely started and if killed the above commands return.

These calls may fail on first attempt, so THERE IS NO WAY TO READ THEIR OUTPUT! I can also use a simple "su -c kill xxx" command line, same result!

EDIT: Started debugging the java_lang_ProcessManager.cpp file in an NDK project with some debugging logs! So here is what I found so far, after the fork() the parent does this:

int result;
int count = read(statusIn, &result, sizeof(int));            <- hangs there
close(statusIn);

Though the child process is not supposed to block on it: That's what the child does (if started at all!):

    // Make statusOut automatically close if execvp() succeeds.
    fcntl(statusOut, F_SETFD, FD_CLOEXEC);                      <- make the parent will not block

    // Close remaining unwanted open fds.
    closeNonStandardFds(statusOut, androidSystemPropertiesFd);  <- hangs here sometimes

    ...

    execvp(commands[0], commands);

    // If we got here, execvp() failed or the working dir was invalid.
    execFailed:
        int error = errno;
        write(statusOut, &error, sizeof(int));
        close(statusOut);
        exit(error);

The child can fail for 2 reproducible reasons: 1- child code is not running, but the parent believes it is! 2- child blocks on closeNonStandardFds(statusOut, androidSystemPropertiesFd);

In either case the read(statusIn...)

Edit
Report

2 Answers

3

Bug fix in Bionic was commited monthes ago, but it still hasn't been included in Android 4.0.4.

answered 2012-07-06T12:20:12.233
0

I have the same problem on ICS (seem to works fine on Android < 4). Did you find a solution?

A simple workaround could be to call the "exec" method in a dedicated thread with a timeout-join so that this situation could be "detected" (yes I know it's not very elegant...)

answered 2012-01-09T09:30:40.440

Your Answer