Проблема с Runtime.exec и Android

У меня проблема, когда я использую Runtime.exec на своем Android-устройстве и просто не могу понять, почему это происходит...

Вот пример тестов, которые я сделал:

public class MainActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Runtime runtime = Runtime.getRuntime();
        for(int i=0; i< 20; i++){
            Log.d("TESTEXEC", "EXEC N°"+i+" : BEGIN");
            try {
                Process process = runtime.exec("/system/bin/ps");
                process.getErrorStream().close();
                process.getOutputStream().close();
                process.getInputStream().close();
                process.waitFor();
            } catch (Throwable e) {
                e.printStackTrace();
            }
            Log.d("TESTEXEC", "EXEC N°"+i+" : END");
        }
    }
}

Итак, в основном, когда этот фрагмент работает, он печатает это:

EXEC N°0 : BEGIN
EXEC N°0 : END
EXEC N°1 : BEGIN
EXEC N°1 : END
...
EXEC N°19 : BEGIN
EXEC N°19 : END

Но вместо этого иногда (похоже, что это немного случайно) он просто печатает

EXEC N°0 : BEGIN

И все блокируется... Кажется, что все рушится в runtime.exec("..."), а process.getErrorStream.close() никогда не вызывается. Еще одна странность: ошибка всегда возникает при первом выполнении.

Вот что я получаю с DDMS: DDMS

Я также получил файл /data/anr/traces.txt, но он бесполезен:

----- pid 11489 at 2011-05-16 15:15:10 -----
Cmd line: com.testexec

DALVIK THREADS:
"main" prio=5 tid=1 NATIVE
  | group="main" sCount=1 dsCount=0 s=N obj=0x4001d8d0 self=0xcca0
  | sysTid=11489 nice=0 sched=0/0 cgrp=unknown handle=-1345021856
  at java.lang.ProcessManager.exec(Native Method)
  at java.lang.ProcessManager.exec(ProcessManager.java:224)
  at java.lang.Runtime.exec(Runtime.java:196)
  at java.lang.Runtime.exec(Runtime.java:285)
  at java.lang.Runtime.exec(Runtime.java:218)
  at com.testexec.MainActivity.onCreate(MainActivity.java:17)
  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2629)
  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2681)
  at android.app.ActivityThread.access$2300(ActivityThread.java:125)
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
  at android.os.Handler.dispatchMessage(Handler.java:99)
  at android.os.Looper.loop(Looper.java:123)
  at android.app.ActivityThread.main(ActivityThread.java:4641)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:521)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
  at dalvik.system.NativeStart.main(Native Method)

"java.lang.ProcessManager" daemon prio=5 tid=8 NATIVE
  | group="main" sCount=1 dsCount=0 s=N obj=0x460969f0 self=0x240f58
  | sysTid=11496 nice=0 sched=0/0 cgrp=unknown handle=2363544
  at java.lang.ProcessManager.watchChildren(Native Method)
  at java.lang.ProcessManager$1.run(ProcessManager.java:87)

"Binder Thread #2" prio=5 tid=7 NATIVE
  | group="main" sCount=1 dsCount=0 s=N obj=0x460895a0 self=0x1248e0
  | sysTid=11495 nice=0 sched=0/0 cgrp=unknown handle=1236304
  at dalvik.system.NativeStart.run(Native Method)

"Binder Thread #1" prio=5 tid=6 NATIVE
  | group="main" sCount=1 dsCount=0 s=N obj=0x46086cf8 self=0x143480
  | sysTid=11494 nice=0 sched=0/0 cgrp=unknown handle=1324096
  at dalvik.system.NativeStart.run(Native Method)

"Compiler" daemon prio=5 tid=5 VMWAIT
  | group="system" sCount=1 dsCount=0 s=N obj=0x46084558 self=0x144560
  | sysTid=11493 nice=0 sched=0/0 cgrp=unknown handle=1153256
  at dalvik.system.NativeStart.run(Native Method)

"JDWP" daemon prio=5 tid=4 VMWAIT
  | group="system" sCount=1 dsCount=0 s=N obj=0x460842a0 self=0x12dc10
  | sysTid=11492 nice=0 sched=0/0 cgrp=unknown handle=1152968
  at dalvik.system.NativeStart.run(Native Method)

"Signal Catcher" daemon prio=5 tid=3 RUNNABLE
  | group="system" sCount=0 dsCount=0 s=N obj=0x460841e8 self=0x124d00
  | sysTid=11491 nice=0 sched=0/0 cgrp=unknown handle=1199296
  at dalvik.system.NativeStart.run(Native Method)

"HeapWorker" daemon prio=5 tid=2 VMWAIT
  | group="system" sCount=1 dsCount=0 s=N obj=0x441e2ee8 self=0x11fdd8
  | sysTid=11490 nice=0 sched=0/0 cgrp=unknown handle=1185776
  at dalvik.system.NativeStart.run(Native Method)

----- end 11489 -----

Я сейчас в отчаянии, поэтому, если у кого-то есть идея, я был бы очень признателен.


person Lyrkan    schedule 16.05.2011    source источник
comment
Решение простое: не используйте Runtime.exec(). В Android SDK нет программ командной строки. Любая программа командной строки, которую вы хотели бы использовать, должна быть переписана как библиотека NDK и вызываться непосредственно из вашего Java-приложения через JNI.   -  person CommonsWare    schedule 16.05.2011
comment
Итак, я должен переписать всю команду ps с помощью NDK, а не просто использовать 5 строк с помощью Runtime.exec? :/   -  person Lyrkan    schedule 16.05.2011
comment
Вы решаете любую проблему, которую пытаетесь решить, используя методы, которые будут работать на любых устройствах, на которые вы пытаетесь ее развернуть. Если это только для вашего телефона, и вы хотите использовать ps, вы можете биться головой о стену, чтобы заставить его работать. Если вы пытаетесь создать приложение для Android Market или аналогичного широкого распространения, не используйте ps, а реализуйте желаемую функциональность каким-либо другим способом, возможно, с помощью NDK.   -  person CommonsWare    schedule 16.05.2011
comment
Какой функциональности вам нужно достичь? 'ps' в основном читает и интерпретирует информацию, содержащуюся в пронумерованных каталогах pid в /proc   -  person Chris Stratton    schedule 16.05.2011
comment
Я не думал читать напрямую /proc/xxx/status. Мне просто нужно получить PID и имена текущих процессов.   -  person Lyrkan    schedule 16.05.2011


Ответы (1)


Скорее всего, эта ошибка исправлена ​​в этом коммите Github. По сути, он блокируется сразу после fork(), но до фактического выполнения exec(), потому что кто-то пытался выполнить malloc.

person dascandy    schedule 14.02.2012