Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: Child process (logcat) keeps running after parent process (app) died

our Android app spawns a logcat shell process and then reads its result for processing. However, when the app stops (e.g. when restarted after recompilation during development), the logcat process will keep running. Here's an example of this behaviour:

processes = new ArrayList<Process>();

try {
  processes.add(Runtime.getRuntime().exec("logcat -v time"));
  processes.add(Runtime.getRuntime().exec("logcat -v time"));
  processes.add(Runtime.getRuntime().exec("logcat -v time"));
  processes.add(Runtime.getRuntime().exec("logcat -v time"));
} catch (IOException e) {
  // oh no!
}

Runtime.getRuntime().addShutdownHook(new Thread() {
  public void run() {
    for (Process p : processes) {
      p.destroy();
    }
  };
});

Add this to the onCreate() method of a test app, start it, then force-stop it using the settings manager. The child processes will keep running, now with a parent-id of 1.

In How to kill logcat process initiated by Android application? it was suggested to use ProcessBuilder, but that wasn't a solution and the process will keep running, too.

In Stop child process when parent process stops it was suggsted to use a shutdown hook - that doesn't work either as demonstrated above.

Thanks!

like image 961
hez Avatar asked Apr 23 '13 15:04

hez


Video Answer


1 Answers

What you could do is spwaning another script of which the sole purpose is to watch your Java program. Whenever it dies, kill all of its children too.

A fragile example:

int pid = android.os.Process.myPid();
String script = "while [ -d /proc/" + pid + " ];do sleep 1;done; killall logcat";
Process p = Runtime.getRuntime().exec("/system/bin/sh", "-c", script);

This assumes that your process does not run as root, thereby only killing its own logcat processes. In your shutdown function, you should first kill the other processes (logcat) and then run p.destroy(); to stop this killer script.

The script above can be improved by removing the use of killall. Instead, get the process IDs of your logcat processes using Reflection (this answer points to http://www.golesny.de/p/code/javagetpid) and pass them to kill.

like image 95
Lekensteyn Avatar answered Sep 28 '22 00:09

Lekensteyn