PDA

Ver la Versión Completa : Matar proceso infinito Android


eldisisi
30/03/15, 05:33:19
Hola, no se si el hilo va aqui pero es que soy nuevo y estoy desesperado, si esta mal que lo cambien de subforo por favor.

A ver, mi problema es que necesito hacer una aplicacion que genere un proceso infinito y luego matarlo. Es un proceso que yo no puedo controlar es decir no puedo escribir codigo dentro de el, una vez ejecuto el comando este proceso se queda leyendo llamadas al sistema de forma infinita.

Lo que yo necesito es paralelamente, pasados X segundos, matar ese proceso.

Lo estoy intentando con android studio con asynctask pero no consigo nada.
Para hacer una "prueba" intento llamar desde un asynctask a un bucle infinito que me escriba un system.out.println de numeros y pasados X segundos intento matarlo desde otro asynctask pero no me funciona, nunca llego a conseguirlo.

¿Alguna idea de lo que puedo hacer?

PD: Estoy viendo que lo unico que puedo hacer, por lo menos con android studio es hacer dos hilos y empezar a "pasar la pelota de tenis" de uno a otro.
Es decir, en cada uno tengo un bucle que muestra un numero, entonces empiezo con el A y muestro un numero y hago un thread.sleep, ahora empieza el B y muestra un numero y hago thread.sleep y sigue el A, asi hasta que se terminan los bucles claro.

¿Esto es lo maximo que puedo hacer? Yo necesitaria que los dos bucles trabajaran en paralelo no en serie. Que quitando el thread.sleep los dos bucles funcionaran a la vez.

Mil gracias.

mocelet
30/03/15, 10:58:01
¿Seguro que necesitas un bucle infinito para algo?

Android está orientado a eventos, si tienes que hacer algo cada cierto tiempo tienes los Handler, los postRunnable, etc., no hace falta un bucle con sleep dentro. Si tienes que hacer algo en respuesta a una acción del usuario ya tienes los eventos de la interfaz.

Dicho esto, los async task normalmente son para ejecutar cosas que tardan poco (lo suficiente para bloquear la interfaz de usuario si se hicieran en el hilo principal) pero no demasiado (podría impedir la ejecución de otras asynctask que estuvieran en cola esperando).

Para bucles infinitos, lo mejor es un Thread separado. La forma "elegante" de matarlo es tener una variable de clase en dicho hilo que puedas controlar desde fuera. Algo del estilo boolean running = true;. En cada iteración del hilo compruebas el valor de running, si es false sales del bucle y el hilo termina de ejecutarse, si es true sigue iterando. Cuando quieras matarlo solo tienes que cambiar esa variable a false que el hilo no volverá a hacer más iteraciones.

Pero vuelvo a la pregunta de antes, igual no necesitas eso...

kriogeN
30/03/15, 12:56:38
Y añadiendo a lo que dice Mocelet, mejor que un Thread son los Services si el proceso va a ser muy largo.

Porque con los Thread si se muere la app se muere (por muere entiendase cualquier cosa, incluso liberación de memoria por el sistema) el Thread, con los Services siguen ejecutándose, y si por cualquier cosa el sistema necesitase memoria después lo vuelve a lanzar (si lo creas como START_STICKY).

Para tu caso el servicio debería hacer lo siguiente:

1) Comprobar que el proceso que quieres lanzar no esté en ejecución, si lo está te esperas los X segundos y después lo matas y finalizas el servicio.

2) En caso contrario lanzas al proceso y esperas los X segundos, después lo matas y finalizas el servicio.

eldisisi
30/03/15, 13:40:40
¿Seguro que necesitas un bucle infinito para algo?

Android está orientado a eventos, si tienes que hacer algo cada cierto tiempo tienes los Handler, los postRunnable, etc., no hace falta un bucle con sleep dentro. Si tienes que hacer algo en respuesta a una acción del usuario ya tienes los eventos de la interfaz.

Dicho esto, los async task normalmente son para ejecutar cosas que tardan poco (lo suficiente para bloquear la interfaz de usuario si se hicieran en el hilo principal) pero no demasiado (podría impedir la ejecución de otras asynctask que estuvieran en cola esperando).

Para bucles infinitos, lo mejor es un Thread separado. La forma "elegante" de matarlo es tener una variable de clase en dicho hilo que puedas controlar desde fuera. Algo del estilo boolean running = true;. En cada iteración del hilo compruebas el valor de running, si es false sales del bucle y el hilo termina de ejecutarse, si es true sigue iterando. Cuando quieras matarlo solo tienes que cambiar esa variable a false que el hilo no volverá a hacer más iteraciones.

Pero vuelvo a la pregunta de antes, igual no necesitas eso...




Y añadiendo a lo que dice Mocelet, mejor que un Thread son los Services si el proceso va a ser muy largo.

Porque con los Thread si se muere la app se muere (por muere entiendase cualquier cosa, incluso liberación de memoria por el sistema) el Thread, con los Services siguen ejecutándose, y si por cualquier cosa el sistema necesitase memoria después lo vuelve a lanzar (si lo creas como START_STICKY).

Para tu caso el servicio debería hacer lo siguiente:

1) Comprobar que el proceso que quieres lanzar no esté en ejecución, si lo está te esperas los X segundos y después lo matas y finalizas el servicio.

2) En caso contrario lanzas al proceso y esperas los X segundos, después lo matas y finalizas el servicio.

Muchas gracias.

Voy a explicarlo un poco mas. Lo que deberia hacer mi aplicacion es, abrir otra aplicacion y registrar todas las llamadas al sistema que haga al kernel de linux.
Para ello monitorizo el proceso Zygote, supongamos que tiene pid 1340.
La unica forma que se me ha ocurrido es hacer esto

main(){
{

Process p1 = Runtime.getRuntime().exec(new String[]{"/system/bin/su" , "-c" , "strace -f -F -p 1340 -o salida.txt"});

Process p2 = Runtime.getRuntime().exec(new String[]{"/system/bin/su" , "-c" , "am start com.google.android.youtube"});

p1.waitfor();

Process p3 = Runtime.getRuntime().exec(new String[]{"/system/bin/su" , "-c" , "killall strace"});

Process p4 = Runtime.getRuntime().exec(new String[]{"/system/bin/su" , "-c" , "killall com.google.android.youtube"});



Ignoremos que llamo a la aplicacion con un exec en vez de con un intent.
El problema es que al hacer la instruccion en negrita, por las pruebas que he hecho creo que waitfor se queda leyendo infinitamente las llamadas al sistema y las escribe en el archivo correspondiente asi que nunca se ejecuta lo que hay por debajo de ella.

Decis por ejemplo que si hago esto ¿Deberia funcionar?


main(){
{

Process p1 = Runtime.getRuntime().exec(new String[]{"/system/bin/su" , "-c" , "strace -f -F -p 1340 -o salida.txt"});

Process p2 = Runtime.getRuntime().exec(new String[]{"/system/bin/su" , "-c" , "am start com.google.android.youtube"});

NUEVO THREAD
while(cierto){
p1.waitfor();
}
FINAL THREAD

Thread.sleep(1000);
Cierto=false;

Process p3 = Runtime.getRuntime().exec(new String[]{"/system/bin/su" , "-c" , "killall strace"});

Process p4 = Runtime.getRuntime().exec(new String[]{"/system/bin/su" , "-c" , "killall com.google.android.youtube"});

mocelet
30/03/15, 14:20:39
Entiendo...

Cuando ejecutas un proceso nativo con getRuntime().exec(...) obtienes la referencia al proceso, puedes matarlo cuando quieras con destroy() del objeto Process.

El waitfor no sé para qué lo usas, eso solo sirve para esperar a que el proceso termine, pero como bien dices es infinito y, por tanto, no termina y no pasa del waitfor porque no llega a la línea que lo mata. Lo del bucle tiene menos sentido todavía.

Y aquí es donde volvemos a que estamos en Android, no en la consola de Java, no puedes hacer un Thread.sleep en el hilo principal (supuesto que ese main() lo estés ejecutando desde el hilo principal). Tendrías que hacer algo así:



[...]
Process p1 = Runtime.getRuntime().exec....
Process p2 = Runtime.getRuntime().exec....


Runnable matar = new Runnable(){
public void run(){
Process p3 = ....
Process p4 = ....
}
}
Handler handler = new Handler();
handler.postDelayed(matar, 1000); // Ejecutará el runnable matar dentro de un segundo



No está probado y uso mucho el autocompletar, así que igual hay algún error de sintaxis por ahí xD

eldisisi
30/03/15, 15:01:50
Entiendo...

Cuando ejecutas un proceso nativo con getRuntime().exec(...) obtienes la referencia al proceso, puedes matarlo cuando quieras con destroy() del objeto Process.

El waitfor no sé para qué lo usas, eso solo sirve para esperar a que el proceso termine, pero como bien dices es infinito y, por tanto, no termina y no pasa del waitfor porque no llega a la línea que lo mata. Lo del bucle tiene menos sentido todavía.

Y aquí es donde volvemos a que estamos en Android, no en la consola de Java, no puedes hacer un Thread.sleep en el hilo principal (supuesto que ese main() lo estés ejecutando desde el hilo principal). Tendrías que hacer algo así:



[...]
Process p1 = Runtime.getRuntime().exec....
Process p2 = Runtime.getRuntime().exec....


Runnable matar = new Runnable(){
public void run(){
Process p3 = ....
Process p4 = ....
}
}
Handler handler = new Handler();
handler.postDelayed(matar, 1000); // Ejecutará el runnable matar dentro de un segundo



No está probado y uso mucho el autocompletar, así que igual hay algún error de sintaxis por ahí xD


Pues el caso es que he probado esto que te digo y sorprendentemente creo que funciona XD pero voy a intentar hacerlo como dices tu.

El caso es que si por lo que he probado si no uso el waitfor jamas llega a escribir las llamadas al sistema en el fichero salida.txt.
Si acabo la ejecucion sin el waitfor, salida.txt estara vacio, es cuando llamo a waitfor cuando escribe.

Voy a tirar lo que me has comentado y os cuento, gracias!

mocelet
30/03/15, 15:11:30
Lo tuyo funciona porque el sleep es de un segundo, pero si eso se ejecuta en el hilo principal dejas el móvil tostado un segundo (no puede ni procesar los eventos de la interfaz de usuario). Si son más segundos Android mata la aplicación por considerar que se ha bloqueado y no funciona correctamente.

eldisisi
30/03/15, 15:21:30
Lo tuyo funciona porque el sleep es de un segundo, pero si eso se ejecuta en el hilo principal dejas el móvil tostado un segundo (no puede ni procesar los eventos de la interfaz de usuario). Si son más segundos Android mata la aplicación por considerar que se ha bloqueado y no funciona correctamente.

Es verdad es verdad, lo he leido. Yo jamas habia trabajado con android y ayer me toco meterme un cursillo intensivo. Como ese sleep lo ejecuto en el hilo principal lo dejo tostado ese tiempo y creo que si superase los 5 segundos como tu dices, me la cerraria.
Asi que lo que tu dices tiene mucho mejor pinta.
Por suerte esta aplicacion es solo para mi asi que no me importa que sea muy usable.