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