Android SWT : Android Software Watchdog Timeout
作用:监控核心服务和核心线程是否卡住,如果判断阻塞 60s ,就会把系统重启,来保证系统恢复正常状态.
Monitor Checker,用于检查是Monitor对象可能发生的死锁, AMS, PKMS, WMS等核心的系统服务都是Monitor对象。预警我们不能长时间持有核心系统服务的对象锁,否则会阻塞很多函数的运行
Looper Checker,用于检查线程的消息队列是否长时间处于工作状态。Watchdog自身的消息队列,Ui, Io, Display这些全局的消息队列都是被检查的对象。此外,一些重要的线程的消息队列,也会加入到Looper Checker中,譬如AMS, PKMS,这些是在对应的对象初始化时加入的。预警我们不能长时间的霸占消息队列,否则其他消息将得不到处理。这两类都会导致系统卡住(System Not Responding)。
对于Looper Checker而言,会判断线程的消息队列是否处于空闲状态。 如果被监测的消息队列一直闲不下来,则说明可能已经阻塞等待了很长时间
对于Monitor Checker而言,会调用实现类的monitor方法,譬如上文中提到的AMS.monitor()方法, 方法实现一般很简单,就是获取当前类的对象锁,如果当前对象锁已经被持有,则monitor()会一直处于wait状态,直到超时,这种情况下,很可能是线程发生了死锁
只要Watchdog没有发现超时的任务,HandlerChecker就会被不停的调度
System Server时就会初始化Watchdog:
final Watchdog watchdog = Watchdog.getInstance();
watchdog.start();
watchdog的添加:
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor
public void monitor() {
synchronized (this) { }
}
导致SWT的原因
1.zygote fork进程卡住
--》线程状态Native,查看是否有Process.zygoteSendArgsAndGetResult,一般是由内存泄漏,内存溢出引起的
2.Dump时间过长
--》 dumpStackTraces 或 dumpStackTraces process
3.SurfaceFlinger过长
-----》 surfaceflinger hang
4.Binder的Server端卡住
-- >::waitForResponse IPCThreadState::talkWithDrive
5.Native方法执行时间过长
-->线程状态Native,PowerManagerService.nativeSetAutoSuspend
6.线程死锁
--》blocked 搜索“held by”
7.确认线程关系
--〉线程状态waiting
1.确认是否为watchdog问题
event log搜索"Blocked in"或者"Watchdog" (logcat -b events 、adb logcat -b events -d )
device log搜索"Blocked in",并且找到出问题的blocked thread(adb wait-for-device logcat)
2.查看下device log里面基本trace和cpu使用信息
3.搜索"Cmd line: system_server"检查30s(watchdog half)和60s(watchdog)的trace,假如trace打印的不一样,代表是系统整体慢导致,
4.不是系统性能导致,查看trace发现主要原因
5.可以看的还有,搜索4后出问题的线程log,可以搜索“”pid tid“”,来看是否有线索,搜索sysrq来看thread状态和trace,比如可以看是否在持有mutex锁,在做binder_ioclt操作等等,或者是否处在D状态(不可中断的异常状态)
adb shell logcat -b all
binder日志:adb shell cat
/proc/binder
案例1:搜索watchdog发生
watchdog: Blocked in handler XXX # 表示HandlerChecker超时了
watchdog: Blocked in monitor XXX # 表示MonitorChecker超时了
******************************************************************
watchdog杀死系统的日志:
Watchdog: *** WATCHDOG KILLING SYSTEM PROCESS: XXX
Watchdog: XXX
Watchdog: "*** GOODBYE!********************************************************************
1.检索到下面信息
W Watchdog: *** WATCHDOG KILLING SYSTEM PROCESS: Blocked in monitor com.android.server.wm.WindowManagerService on foreground thread (android.fg)
2.打开system_server进程的traces,检索 android.fg 可以快速定位到该线程的函数调用栈:(adb shell ps | grep system_server )
"android.fg" prio=5 tid=25 Blocked
| group="main" sCount=1 dsCount=0 obj=0x12eef900 self=0x7f7a8b1000
| sysTid=973 nice=0 cgrp=default sched=0/0 handle=0x7f644e9000
| state=S schedstat=( 3181688530 2206454929 8991 ) utm=251 stm=67 core=1 HZ=100
| stack=0x7f643e7000-0x7f643e9000 stackSize=1036KB
| held mutexes=
at com.android.server.wm.WindowManagerService.monitor(WindowManagerService.java:13125)
- waiting to lock <0x126dccb8> (a java.util.HashMap) held by thread 91
at com.android.server.Watchdog$HandlerChecker.run(Watchdog.java:204)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:194)
at android.os.HandlerThread.run(HandlerThread.java:61)
at com.android.server.ServiceThread.run(ServiceThread.java:46)
3.由上知道了91进程阻塞,检索 tid=91
"Binder_C" prio=5 tid=91 Native
| group="main" sCount=1 dsCount=0 obj=0x12e540a0 self=0x7f63289000
| sysTid=1736 nice=0 cgrp=default sched=0/0 handle=0x7f6127c000
| state=S schedstat=( 96931835222 49673449591 260122 ) utm=7046 stm=2647 core=2 HZ=100
| stack=0x7f5ffbc000-0x7f5ffbe000 stackSize=1008KB
| held mutexes=
at libcore.io.Posix.writeBytes(Native method)
at libcore.io.Posix.write(Posix.java:258)
at libcore.io.BlockGuardOs.write(BlockGuardOs.java:313)
at libcore.io.IoBridge.write(IoBridge.java:537)
at java.io.FileOutputStream.write(FileOutputStream.java:186)
at com.android.internal.util.FastPrintWriter.flushBytesLocked(FastPrintWriter.java:334)
at com.android.internal.util.FastPrintWriter.flushLocked(FastPrintWriter.java:355)
at com.android.internal.util.FastPrintWriter.appendLocked(FastPrintWriter.java:303)
at com.android.internal.util.FastPrintWriter.print(FastPrintWriter.java:466)
- locked <@addr=0x134c4910> (a com.android.internal.util.FastPrintWriter$DummyWriter)
at com.android.server.wm.WindowState.dump(WindowState.java:1510)
at com.android.server.wm.WindowManagerService.dumpWindowsNoHeaderLocked(WindowManagerService.java:12279)
at com.android.server.wm.WindowManagerService.dumpWindowsLocked(WindowManagerService.java:12266)
at com.android.server.wm.WindowManagerService.dump(WindowManagerService.java:12654)
- locked <0x126dccb8> (a java.util.HashMap)
at android.os.Binder.dump(Binder.java:324)
at android.os.Binder.onTransact(Binder.java:290)
4.解决方法:在这个IO写操作上加一个超时机制,并且这个超时小于Watchdog的超时,不就可以让线程释放它所占有的锁了吗
案例2:
1.检索到
10-14 17:10:51.548 892 1403 W Watchdog: *** WATCHDOG KILLING SYSTEM PROCESS: Blocked in handler on ActivityManager (ActivityManager)
2.分析出红色的是时间点和进程号,找到trace.txt
3.搜索ActivityManager
"ActivityManager" prio=5 tid=17 TimedWaiting
| group="main" sCount=1 dsCount=0 obj=0x12c0e6d0 self=0x7f84caf000
| sysTid=938 nice=-2 cgrp=default sched=0/0 handle=0x7f7d887000
| state=S schedstat=( 107864628645 628257779012 60356 ) utm=7799 stm=2987 core=2 HZ=100
| stack=0x7f6e68f000-0x7f6e691000 stackSize=1036KB
| held mutexes=
at java.lang.Object.wait!(Native method)
- waiting on <0x264ff09d> (a com.android.server.am.ActivityManagerService$5)
at java.lang.Object.wait(Object.java:422)
at com.android.server.am.ActivityManagerService.dumpStackTraces(ActivityManagerService.java:5395)
at com.android.server.am.ActivityManagerService.dumpStackTraces(ActivityManagerService.java:5282)
at com.android.server.am.ActivityManagerService$AnrActivityManagerService.dumpStackTraces(ActivityManagerService.java:22676)
at com.mediatek.anrmanager.ANRManager$AnrDumpMgr.dumpAnrDebugInfoLocked(SourceFile:1023)
at com.mediatek.anrmanager.ANRManager$AnrDumpMgr.dumpAnrDebugInfo(SourceFile:881)
at com.android.server.am.ActivityManagerService.appNotResponding(ActivityManagerService.java:6122)
- locked <0x21c77912> (a com.mediatek.anrmanager.ANRManager$AnrDumpRecord)
at com.android.server.am.BroadcastQueue$AppNotResponding.run(BroadcastQueue.java:228)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:192)
at android.os.HandlerThread.run(HandlerThread.java:61)
at com.android.server.ServiceThread.run(ServiceThread.java:46)
4.分析得知AMS设计了一个200毫秒的超时锁。
5.在sys_log中检索”ANR in”关键字或在event_log中检索”anr”关键字
10-14 17:10:04.215 892 938 E ANRManager: ANR in com.android.systemui, time=27097912
10-14 17:10:04.215 892 938 E ANRManager: Reason: Broadcast of Intent { act=android.intent.action.TIME_TICK flg=0x50000114 (has extras) }
10-14 17:10:04.215 892 938 E ANRManager: Load: 89.22 / 288.15 / 201.91
10-14 17:10:04.215 892 938 E ANRManager: Android time :[2015-10-14 17:10:04.14] [27280.396]
10-14 17:10:04.215 892 938 E ANRManager: CPU usage from 17016ms to 0ms ago:
10-14 17:10:04.215 892 938 E ANRManager: 358% 23682/float_bessel: 358% user + 0% kernel
10-14 17:10:04.215 892 938 E ANRManager: 57% 23604/debuggerd64: 3.8% user + 53% kernel / faults: 11369 minor
10-14 17:10:04.215 892 938 E ANRManager: 2% 892/system_server: 0.9% user + 1% kernel / faults: 136 minor
ANR
ANR弹出对话框提示用户
InputDispatching Timeout:5秒内无法响应屏幕触摸事件或键盘输入事件
BroadcastQueue Timeout :在执行前台广播(BroadcastReceiver)的onReceive()函数时10秒没有处理完成,后台为60秒
ContentProvider Timeout :ContentProvider的publish在10s内没进行完
Service Timeout :前台服务20秒内,后台服务在200秒内没有执行完毕
注意:耗时操作本身是不会产生ANR的,导致ANR的根本还是应用程序无法在一定时间内响应用户的操作。
主线程慢代码
主线程IO
锁竞争
死锁
1.UI线程尽量只做跟UI相关的工作
2.耗时的工作(比如数据库操作,I/O,连接网络或者别的有可能阻碍UI线程的操作)把它放入单独的线程处理
3.尽量用Handler来处理UI thread和别的thread之间的交互
4.实在绕不开主线程,可以尝试通过Handler延迟加载
5.广播中如果有耗时操作,建议放在IntentService中去执行,或者通过goAsync() + HandlerThread分发执行。
Handler机制:
Looper.loop 为什么不会导致死锁?
1.如果不用Looper.loop的话应用也就退出了,代码其实就是在这个循环里面去执行的,固然不会阻塞了
2.主线程大多数时候都是处于休眠状态,并不会消耗大量CPU资源
3.若是某个消息处理时间过长,好比你在onCreate(),onResume()里面处理耗时操做,那么下一次的消息好比用户的点击事件不能处理了,整个循环就会产生卡顿,时间一长就成了ANR
总结:Looer.loop()方法可能会引发主线程的阻塞,但只要它的消息循环没有被阻塞,能一直处理事件就不会产生ANR异常。
参考:Android ANR(应用无响应)_mysimplelove的博客-CSDN博客_android 无响应
Watchdog机制以及问题分析_水无声风无痕的博客-CSDN博客_watchdog 多核