2

My UI blocked only in 4.0.* by using clause:"Runtime.getRuntime().exec("cat proc/meminfo");". Is there something wrong in following code? Thanks in advance.

Log:

03-27 13:37:18.545: I/MyActivity(19730): ini().429: 1332826638549
03-27 13:37:18.545: I/MyActivity(19730): ini().434: 1332826638549
03-27 13:37:18.865: D/dalvikvm(19611): GC_CONCURRENT freed 389K, 6% free 9733K/10311K, paused 1ms+2ms

Code:

Log.i(getClass().getName(), "ini().434: " + System.currentTimeMillis());

try {
    Process process = Runtime.getRuntime().exec("cat proc/meminfo");//! hang here       
    Log.i(getClass().getName(), "ini().436: " + System.currentTimeMillis());
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));                            
    Log.i(getClass().getName(), "ini().438: " + System.currentTimeMillis());
    String str = bufferedReader.readLine();
    totleMemory = Long.parseLong(str.replaceAll("\\s+", "").replaceAll("[a-zA-Z]", "").replaceAll(":", ""));                            
    Log.i(getClass().getName(), "ini().441: " + System.currentTimeMillis());
    totleMemory *= 1024;
    } catch (Exception e) {
    }   

Log.i(getClass().getName(), "ini().446: " + System.currentTimeMillis());
Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
thecr0w
  • 2,148
  • 4
  • 33
  • 59

3 Answers3

2

Thank you all the same, @Jared Burrows. I read some article like "[When Runtime.exec() won't Navigate...][1]" and replaced it with following code for same purpose:

//Process process = Runtime.getRuntime().exec("/system/bin/cat /proc/meminfo");
FileReader fr = new FileReader("cat /proc/meminfo");
BufferedReader reader = new BufferedReader(fr);
...more

I assume that there is some potential problem when this method is called in UI Thread.Much more similar thread in stackoverflow was post here:

Problem with Runtime.exec and Android

Community
  • 1
  • 1
thecr0w
  • 2,148
  • 4
  • 33
  • 59
1

I have the same problem in Android 4.0.3. I found the deadlock happen at below by using gdb

    bionic/libc/bionic/pthread-atfork.c
    void __bionic_atfork_run_child()
    {
    ...
        pthread_mutex_unlock(&handler_mutex); <-- deadlock here

And using the same code to test in Android 4.2 is ok. So I use git to find the solution in bionic. And I got the solution and have fixed this issue by patching commit 34e89c232dd5645fe3b5f9b40856d8e3e4cae57a

Here's the root cause: The atfork uses the mutex handler_mutex to protect the atfork_head. The parent will call __bionic_atfork_run_prepare() to lock the handler_mutex, and need both the parent and child to unlock their own copy of handler_mutex after fork. At that time, the owner of hanlder_mutex is set as the parent. If we apply the kernel_id fix, then the child's kernel_id will be set as child's tid.

The handler_mutex is a recursive lock, and pthread_mutex_unlock(&hander_mutex) will fail because the mutex owner is the parent, while the current tid (__get_thread()->kernel_id) is child, not matched with the mutex owner. At that time, the handler_mutex is left in lock state.If the child wants to fork other process after than, then it will try to lock handler_mutex, and then be deadlocked.

0

I just opened the terminal app on my phone which is running Android 4.0+ and ran your command "cat /proc/meminfo". I did not allow the app to have "su" or "root" permissions, running as a normal app. The command completed successfully.

So if I can run it via command line using an application running on the phone, I am sure I can do via ADB shell and most likely in Java.

I've used this code in my applications before:

try 
    {
    Process process = Runtime.getRuntime().exec("/system/bin/cat /proc/meminfo");
    BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
    int read;
    char[] buffer = new char[4096];
    StringBuffer output = new StringBuffer();
    while ((read = reader.read(buffer)) > 0) 
    {
        output.append(buffer, 0, read);
    }
    reader.close();
    process.waitFor();

    // wrap this in a method and return the string
    return output.toString();
} catch (Exception e) {
}

However, when I have tried to run commands what I do not have the correct permissions to run, I have gotten that error "GC_CONCURRENT".

Regards,

Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
  • MasterJB,Thank you all the same. – thecr0w Apr 05 '12 at 03:10
  • BTW, do you agree with this kind of saying: As there are three streams (stdin, stdout, stderr) which we could get by 1.getErrorStream() 2.getInputStream() 3.getOutputStream(), and the input stream is only got after error stream is finished if some unexpected error occurs. Or there will be blocking, is that so? – thecr0w Apr 05 '12 at 03:21
  • I am not sure I have only used InputStream for my applications. Are you still getting an error or are you doing more research? – Jared Burrows Apr 05 '12 at 03:23
  • Also, I tested "cat /proc/meminfo" in Android 2.3.3 and 4.0 using a Terminal app that wasn't using Root permissions for make sure :) – Jared Burrows Apr 05 '12 at 03:25
  • This happens in 4.0.3 sometimes, bu not often. – thecr0w Apr 10 '12 at 12:26
  • Hmm, did this help? Have you figured it out yet? – Jared Burrows Apr 10 '12 at 12:29
  • "Hmm, did this help? Have you figured it out yet? – MasterJB" No, Some users keep reporting that issue till now. I'm pretty sure the 4.x problem is caused by "Runtime.getRuntime()". – thecr0w Apr 17 '12 at 11:23