Runtime.exec()bug:挂起而不提供Process对象

时间:2011-12-31 13:30:40

标签: android process exec

我是否使用此:

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

或那:

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

我得到了相同的结果:它经常在exec()或start()调用中挂起,无论我尝试做什么! 运行它的线程甚至不能被Thread.interrupt()中断!子进程肯定是启动的,如果被杀死,上面的命令就会返回。

这些调用可能会在第一次尝试时失败,所以没有办法阅读他们的输出!我也可以使用一个简单的“su -c kill xxx”命令行,结果相同!

编辑:使用一些调试日志开始调试NDK项目中的java_lang_ProcessManager.cpp文件!所以这就是我到目前为止所发现的,在fork()之后,父进行了这个:

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

虽然孩子的过程不应该阻止它:这就是孩子的行为(如果开始的话!):

    // 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);

孩子可能因为两个可重复的原因而失败: 1-子代码没有运行,但父母认为它是! 2-儿童街区         closeNonStandardFds(statusOut,androidSystemPropertiesFd);

在任何一种情况下,父级中的read(statusIn ...)都以死锁结束!并且子进程被遗忘(无法访问,pid未知,没有Process对象)!

4 个答案:

答案 0 :(得分:6)

此问题已在Jelly Bean (Android 4.1)中修复,但未在ICS (4.0.4)中修复,我想它永远不会在ICS中修复。

答案 1 :(得分:4)

以上解决方案在任何方面都不可靠,在某些设备上造成更多问题!

所以我恢复了标准.exec()并继续挖掘...

查看挂起的子代码,我注意到子进程在尝试关闭从父继承的所有文件描述符时都会挂起(除了在exec()调用中创建的文件描述符除外)!< / p>

所以我在整个应用程序代码中搜索任何BufferedReader / Writer和类似的类,以确保在调用exec()时它们会被关闭!

问题的频率大大降低,实际上在我调用exec()之前删除了最后打开的文件描述符时,再也没有出现过。

NB:确保SU二进制文件是最新的,它实际上也可能导致此问题!

享受您的搜索;)

答案 2 :(得分:3)

Bionic中的错误修复时间是commited个月前,但它仍未包含在Android 4.0.4中。

答案 3 :(得分:0)

我在ICS上遇到同样的问题(似乎在Android&lt; 4上工作正常)。你找到了解决方案吗?

一个简单的解决方法是在具有超时连接的专用线程中调用“exec”方法,以便可以“检测”这种情况(是的,我知道它不是很优雅......)