watchdog杀死system_server导致系统重启问题分析流程

下面是最近在解一个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不需要解。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章