2014-07-29

ANR

 

1. What's ANR

An ANR happens when some long operation takes place in the "main" thread. This is the event loop thread, and if it is busy, Android cannot process any further GUI events in the application, and thus throws up an ANR dialog. See http://developer.android.com/training/articles/perf-anr.html

2. ANR output format


ANR output displays threads information in the following order: - DVM mutexes (only for ‘main’ thread) - Thread’s info - Thread stack

1.1.DVM mutexes format

 "(mutexes: tll=%x tsl=%x tscl=%x ghl=%x hwl=%x hwll=%x)", where
        tll  - thread list lock,
        tsl  - thread suspend lock,
        tscl - thread suspend count lock,
        dhl  - GC heap lock,
        hwl  - heap worker lock,
        hwll - heap worker list lock

1.2.Thread's info format Thread’s info format - first line

“%name %priority %tid %status”, where
        name     - thread name,
        priority - thread priority,
        tid      - thread id,
        status   - thread status

Thread’s info format - second line

" group=%s sCount=%d dsCount=%d obj=%p self=%p“, where
group   - group name,
sCount  - suspend count,
dsCount - debug suspend count,
obj     - Linux thread that we are associated with
self    - self reference

Thread’s info format - third line

 " sysTid=%d nice=%d sched=%d/%d cgrp=%s handle=%d", where
sysTid - Linux thread id,
nice   - Linux "nice“ priority (lower numbers indicate higher priority),
sched  - scheduling priority,
cgrp   - scheduling group buffer
handle - thread handle

Stack trace The stack trace contains functions call stack at the moment ‘dumpstate’ command was called. If the thread is in the TIMED_WAIT state it also contains the address of the object the current thread is waiting for e.g

2. Thread status


Thread status can be one of the following values:

ZOMBIE       - terminated thread
RUNNABLE     - runnable or running now
TIMED_WAIT   - timed waiting in Object.wait()
MONITOR      - blocked on a monitor
WAIT         - waiting in Object.wait()
INITIALIZING - allocated, not yet running
STARTING     - started, not yet on thread list
NATIVE       - off in a JNI native method
VMWAIT       - waiting on a VM resource
SUSPENDED    - suspended, usually by GC or debugger
UNKNOWN      - thread is in the undefined state

3. Example. Here's a Normandy ANR error and how I identified it by checking trace.

1. Check android.server.ServerThread->search 'waiting to lock'->get 'held by..'. Searching 'waiting' is more genetically

1281 "android.server.ServerThread" prio=5 tid=12 MONITOR
1282   | group="main" sCount=1 dsCount=0 obj=0x424f1fd8 self=0x4f810008
1283   | sysTid=583 nice=-2 sched=0/0 cgrp=apps handle=1337892560
1284   | schedstat=( 0 0 0 ) utm=1196 stm=106 core=0
1285   at com.android.server.AlarmManagerService$ResultReceiver.onSendFinished(AlarmManagerService.java:~1034)
1286   - waiting to lock <0x42876cb8> (a java.lang.Object) held by tid=23 (AlarmManager)

2. In this case, search AlarmManager? based on what we got in 'held by..' of step 1

1070 "AlarmManager" prio=5 tid=23 MONITOR
1071   | group="main" sCount=1 dsCount=0 obj=0x42985c58 self=0x4fd91a78
1072   | sysTid=639 nice=0 sched=0/0 cgrp=apps handle=1337835624
1073   | schedstat=( 0 0 0 ) utm=15 stm=5 core=0
1074   at com.android.server.PowerManagerService.acquireWakeLock(PowerManagerService.java:~911)
1075   - waiting to lock <0x424feaf8> (a com.android.server.PowerManagerService$LockList) held by tid=9 (Binder_1)

3. check 'Binger_1' from step 2 to figure out where's lock place in source.

1324 "Binder_1" prio=5 tid=9 NATIVE
1325   | group="main" sCount=1 dsCount=0 obj=0x424ed8e8 self=0x50bae4b0
1326   | sysTid=580 nice=0 sched=0/0 cgrp=apps handle=1345522072
1327   | schedstat=( 0 0 0 ) utm=1745 stm=912 core=0
1328   at com.android.server.PowerManagerService.nativeSetScreenState(Native Method)
1329   at com.android.server.PowerManagerService.setScreenStateLocked(PowerManagerService.java:1928)
1330   at com.android.server.PowerManagerService.setPowerState(PowerManagerService.java:2060)
1331   at com.android.server.PowerManagerService.setPowerState(PowerManagerService.java:1963)
1332   at com.android.server.PowerManagerService.acquireWakeLockLocked(PowerManagerService.java:1063)
1333   at com.android.server.PowerManagerService.acquireWakeLock(PowerManagerService.java:912)
1334   at android.os.IPowerManager$Stub.onTransact(IPowerManager.java:62)
1335   at android.os.Binder.execTransact(Binder.java:367)
1336   at dalvik.system.NativeStart.run(Native Method)

Here's PowerManagerService?.java:~911

 900     public void acquireWakeLock(int flags, IBinder lock, String tag, WorkSource ws) {
 901         int uid = Binder.getCallingUid();
 902         int pid = Binder.getCallingPid();
 903         if (uid != Process.myUid()) {
 904             mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
 905         }
 906         if (ws != null) {
 907             enforceWakeSourcePermission(uid, pid);
 908         }
 909         long ident = Binder.clearCallingIdentity();
 910         try {
>> 911             synchronized (mLocks)  {             
 912                 acquireWakeLockLocked(flags, lock, uid, pid, tag, ws);
 913             }
 914         } finally {
 915             Binder.restoreCallingIdentity(ident);
 916         }
 917     }

 

No comments: