下面是最近在解一个monkey测试过程中系统重启的bug的分析过程,从这里我们可以看一下对于watchdog杀死死锁进程的一般分析流程。(这里当是一个笔记,没有详细按着文章的逻辑来整理词汇和语句 汗汗汗)
1. watchdog: Blocked in handler on ActivityManager (ActivityManager)
说明ActivityManager这个线程被blocked了(ActivityManager是system_server的一个线程)
2. 查看ActivityManager线程的堆栈状态:
"ActivityManager" prio=5 tid=15 Blocked
at com.android.server.am.ActivityManagerService$MainHandler.handleMessage(ActivityManagerService.java:1784)
- waiting to lock <0x1a4c832a> (a com.android.server.am.ActivityManagerService) held by thread 61
该线程在等待锁<0x1a4c832a>,这个锁被thread 61所持有
3.查看thread 61的堆栈状态:
"Binder_5" prio=5 tid=61 Native
at android.app.IActivityController$Stub$Proxy.appCrashed(IActivityController.java:222)
at com.android.server.am.ActivityManagerService.crashApplication(ActivityManagerService.java:12297)
- locked <0x1a4c832a> (a com.android.server.am.ActivityManagerService)
at com.android.server.am.ActivityManagerService.handleApplicationCrashInner(ActivityManagerService.java:11838)
at com.android.server.am.ActivityManagerService.handleApplicationCrash(ActivityManagerService.java:11820)
这里可以看到tid=61的线程是AMS中的一个binder线程,而这个binder线程正在处理app crash,即在crashApplication方法中。由于
当前处于monkey测试状态,所以会进入ActivityController的appCrashed方法。大致猜测可能是monkey进程的appCrashed被blocked住了,所以
AMS的crashApplication方法也被blocked住了。
4,下面看一下monkey进程,搜一下“appCrashed”关键字,有如下log:
"Binder_3" prio=5 tid=13 Blocked
at com.android.commands.monkey.Monkey$ActivityController.appCrashed(Monkey.java:330)
- waiting to lock <0x12a7bb9b> (a com.android.commands.monkey.Monkey) held by thread 1
at android.app.IActivityController$Stub.onTransact(IActivityController.java:92)
at android.os.Binder.execTransact(Binder.java:446)
果不其然,appCrashed方法在等待锁<0x12a7bb9b>,而这个锁被thread 1锁持有。
5.看一下thread 1:
"main" prio=5 tid=1 Native
at libcore.io.BlockGuardOs.read(BlockGuardOs.java:230)
at libcore.io.IoBridge.read(IoBridge.java:512)
at java.io.FileInputStream.read(FileInputStream.java:177)
at java.io.InputStreamReader.read(InputStreamReader.java:231)
- locked <@addr=0x12c518a0> (a java.lang.ProcessManager$ProcessInputStream)
at java.io.BufferedReader.fillBuf(BufferedReader.java:145)
at java.io.BufferedReader.readLine(BufferedReader.java:397)
- locked <@addr=0x12c51ac0> (a java.io.InputStreamReader)
at com.android.commands.monkey.Monkey.commandLineReport(Monkey.java:458)
at com.android.commands.monkey.Monkey.getBugreport(Monkey.java:497)
at com.android.commands.monkey.Monkey.runMonkeyCycles(Monkey.java:1078)
看到这里我们就明白了,实际上是IO阻塞了。这里可以大致说一下:在monkey测试的时候,当遇到anr\app crash等异常
情况时,monkey会把这些异常情况写入文件中以供我们分析。monkey在写文件时,是调用“bugreport”这个shell命令来获取当前
系统各进程的各线程的堆栈情况和状态的,而bugreport会得到大量的信息,所以如果在monkey测试时连续遇到anr/crash,有可能会导致
这个写文件的过程很长,这样AMS通知monkey的appCrashed的方法就会被blocked住,进而导致AMS被blocked住。
综述:
monkey测试时,由于连续遇到anr/crash,导致monkey在写bugreport信息到文件的时间(getBugreport)过长。这样如果再次发生anr/crash时,AMS调用monkey的appCrashed的方法
通知monkey当前又有anr/crash发生,但是由于appCrashed方法和getBugreport方法持有同一把锁(monkey对象),所以appCrashed就拿不到锁被blocked住,进而导致AMS的
crashApplication方法被blocked住。而crashApplication持有的所对象是AMS本身,这样就导致所有持有AMS对象为锁的线程都被blocked住,这里面包括ActivityManager线程。这样
watchdog在定期锁检查的时候,就发现ActivityManager线程被blocked了,就会杀死System_server导致系统重启。
所以:这是monkey测试本身的io操作导致的持锁过久,最终导致system_server被杀死的问题。这个bug不需要解。
转自:http://blog.csdn.net/stephen8341/article/details/52642991