Ошибка Runtime.exec (): зависает без предоставления объекта Process - PullRequest
18 голосов
/ 31 декабря 2011

Использую ли я это:

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, тот же результат!

РЕДАКТИРОВАТЬ: Начата отладка файла java_lang_ProcessManager.cpp в проекте NDK с некоторыми журналами отладки! Итак, вот что я нашел до сих пор, после 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);

Ребенок может потерпеть неудачу по 2 воспроизводимым причинам: 1- дочерний код не запущен, но родитель считает, что это так! 2- дочерние блоки на closeNonStandardFds (statusOut, androidSystemPropertiesFd);

В любом случае чтение (statusIn ...) в родительском элементе заканчивается тупиком! и дочерний процесс остается мертвым (и к нему нельзя получить доступ, pid неизвестен, нет объекта Process)!

Ответы [ 4 ]

6 голосов
/ 10 июля 2012

Эта проблема исправлена ​​в Jelly Bean (Android 4.1) , но не в ICS (4.0.4) , и я думаю, что она никогда не будет исправлена ​​в ICS.

4 голосов
/ 03 июля 2012

Вышеупомянутое решение не оказалось надежным ни в каком случае, вызывая больше проблем на некоторых устройствах!

Поэтому я вернулся к стандартному .exec () и продолжал копать ...

Глядя на зависший дочерний код, я заметил, что дочерний процесс зависает при попытке закрыть все файловые дескрипторы, унаследованные от родительского (кроме того, который создан в вызове exec ())!

Поэтому я ищу во всем коде приложения любые BufferedReader / Writer и подобные классы, чтобы убедиться, что они будут закрыты при вызове exec ()!

Частота проблемы была значительно снижена и фактически никогда не возникалаеще раз, когда я удалил последний открытый дескриптор файла перед вызовом exec ().

NB: Убедитесь, что двоичный файл SU обновлен, это действительно может вызвать эту проблему!

Приятного поиска;)

3 голосов
/ 06 июля 2012

Исправлена ​​ошибка в Bionic зафиксировано месяц назад, но она до сих пор не включена в Android 4.0.4.

0 голосов
/ 09 января 2012

У меня такая же проблема на ICS (кажется, работает нормально на Android <4). Вы нашли решение? </p>

Простой обходной путь может состоять в том, чтобы вызвать метод "exec" в выделенном потоке с помощью timeout-join, чтобы эту ситуацию можно было "обнаружить" (да, я знаю, что это не очень элегантно ...)

...