systemserver为啥很少同步跨进程调用app/DeadSystemException相关问题分析套路

背景:

有学员分享了一个问题,说monkey测试过程中有一系列问题属于同类的,具体看如下截图:
在这里插入图片描述
可以看到这里的有很多应用都进行了crash,而且crash原因居然都是写着
DeadSystemException: The system died; earlier logs will point to the root cause

即系统死了这种异常,但是提示也说明需要看更早的日志才可以找到根本原因,即注意这里说的DeadSystemException一般都是需要往前面分析日志找到根本原因

初步分析

一般DeadSystemException: The system died; earlier logs will point to the root cause
打印这类异常时候需要继续往前看日志,看看systemserver到底发生了什么。
往上看日志可以发现如下:

03-29 13:55:30.675   510   535 W Watchdog: *** WATCHDOG KILLING SYSTEM PROCESS: Blocked in monitor com.android.server.wm.WindowManagerService on foreground thread (android.fg)
03-29 13:55:30.676   510   535 W Watchdog: android.fg annotated stack trace:
03-29 13:55:30.676   510   535 W Watchdog:     at com.android.server.wm.WindowManagerService.monitor(WindowManagerService.java:6396)
03-29 13:55:30.677   510   535 W Watchdog:     - waiting to lock <0x048421d2> (a com.android.server.wm.WindowManagerGlobalLock)
03-29 13:55:30.677   510   535 W Watchdog:     at com.android.server.Watchdog$HandlerChecker.run(Watchdog.java:233)
03-29 13:55:30.678   510   535 W Watchdog:     at android.os.Handler.handleCallback(Handler.java:883)
03-29 13:55:30.678   510   535 W Watchdog:     at android.os.Handler.dispatchMessage(Handler.java:100)
03-29 13:55:30.678   510   535 W Watchdog:     at android.os.Looper.loop(Looper.java:214)
03-29 13:55:30.678   510   535 W Watchdog:     at android.os.HandlerThread.run(HandlerThread.java:67)
03-29 13:55:30.678   510   535 W Watchdog:     at com.android.server.ServiceThread.run(ServiceThread.java:44)
03-29 13:55:30.678   510   535 W Watchdog: *** GOODBYE!

明显可以看到确实这个时候系统都触发了watchdog,kill了system process,那么原因还是
waiting to lock <0x048421d2> (a com.android.server.wm.WindowManagerGlobalLock)
即在等待这把锁
这里再往上看可以看到有一个系统anr打印
03-29 13:52:19.196 510 535 I ActivityManager: Dumping to /data/anr/anr_2024-03-29-13-52-19-196

可以看看这个anr的dump日志

注意从上面可以看出watchdog信息可以看出是WindowManagerService的全局锁一直是获取不到,说明有地方长期占用了WindowManagerGlobalLock这个锁,可以在dump中搜一下Blocked关键字,结果如下:
在这里插入图片描述
点开一个查看详情

在这里插入图片描述

可以看到都是在等待同一个锁
lock <0x048421d2> (a com.android.server.wm.WindowManagerGlobalLock)

那么这个锁是被谁持有着不释放呢?
继续查看,查看方法可以搜thread 236,或者是搜索锁对象地址 0x048421d2
在这里插入图片描述

所以这个tid 236线程就是持有锁导致其他线程无法获取锁的根本
但是从堆栈来看看,明显这个是一个跨进程调用startActivity,systemserver在这个binder线程中居然还发起了同步的跨进程调用,即activityStarting,这个调用居然systemserver还是bp的角色。
android.app.IActivityController S t u b Stub StubProxy.activityStarting(IActivityController.java:273)

这里就奇怪了,systemserver一般自己作为bp时候的跨进程调用那都是oneway的异步调用,怎么会出现还有同步调用的情况,去aidl确认一下:

在这里插入图片描述
可以看到确实是没有oneway字样,正常其他跨进程调用都是有oneway的,比如如下IApplicationThread接口:
在这里插入图片描述

不过这个IActivityController接口正常情况都是无法使用的

/**
 * Testing interface to monitor what is happening in the activity manager
 * while tests are running.  Not for normal application development.
 * {@hide}
 */
interface IActivityController

可以看到只用于测试哈情况,其实这份日志本身是基于monkey测试的

总结直接问题点:
基于上面分析那就基本上明白了导致系统死锁的直接原因,那就是因为systemserver发起了个同步的跨进程调用,这个跨进程调用半天没有得到对方回应,导致systemserver一直卡在这个同步调用这里。

问题继续展望

上面虽然分析出来了一个直接原因,但是也没有找到根本原因,上面说的systemserver跨进程半天没有得到app层面回应,导致一直卡住,那么为啥会被一直卡住?正常跨进程调用应该很快才对,怎么能一直卡住呢?当前binder到底发生了什么呢?

需要进一步追踪根本原因,目前的日志和材料已经不够了,需要更多的日志,比如kernel日志,binder相关调用日志确认出到底是卡在了 app进程,它一直业务繁忙没处理完这个binder调用,还是说binder调用就是没到app进程等,最好还需要有app进程执行的一个线程情况和所有线程在出现问题时候执行的堆栈。

当然也不追查根本原因也可以有对应的规避方案:

可以考虑这个跨进程调用可能会存在长耗时,可以考虑改善这个跨进程调用为不获取锁等情况,修改可能较大,但是影响小一点,只会影响monkey进程业务

更多framework实战干货,请关注下面“千里马学框架”

响应速度问题分析套路(以 Systrace 为主) 确认前提条件(老化,数据量、下等)、操作步骤、问题现象,本地复现 需要明确测试标准 启动时间的起点是哪里 启动时机的终点是哪里 抓取所需的日志信息(Systrace、常规 log 等) 首先分析 Systrace,大概找出差异的点 首先查看应用耗时点,分析对比机差异,这里可以把应用启动阶段分成好几段来看,来对比分析是哪部分时间增加 Application 创建 Activity 创建 第一个 doFrame 后续内容加 应用自己的 Message 分析应用耗时的点 是否某一段方法自身执行耗时比较久(Running 状态) –> 应用自身问题 主线程是否有大段 Running 状态,但是底下没有任何堆栈 –> 应用自身问题,加 TraceTag 或者使用 TraceView 来找到对应的代码逻辑 是否在等 Binder 耗时比较久(Sleep 状态) –> 检测 Binder 服务端,一般是 SystemServer 是否在等待子线程返回数据(Sleep 状态) –> 应用自身问题,通过查看 wakeup 信息,来找到依赖的子线程 是否在等待子进程返回数据(Sleep 状态) –> 应用自身问题,通过查看 wakeup 信息,来找到依赖的子进程或者其他进程(一般是 ContentProvider 所在的进程) 是否有大量的 Runnable –> 系统问题,查看 CPU 部分,看看是否已经跑满 是否有大量的 IO 等待(Uninterruptible Sleep | WakeKill - Block I/O) –> 检查系统是否已经低内存 RenderThread 是否执行 dequeueBuffer 和 queueBuffer 耗时 –> 查看 SurfaceFlinger 如果分析是系统的问题,则根据上面耗时的点,查看系统对应的部分,一般情况要优先查看系统是否异常,参考上面列出的的系统原因,主要看下面四个区域(Systrace) Kernel 区域 查看关键任务是否跑在了小核 –> 一般小核是 0-3(也有特例),如果启动时候的关键任务跑到了小核,执行速度也会变慢 查看频率是否没有跑满 –> 表现是核心频率没有达到最大值,比如最大值是 2.8Ghz,但是只跑到了 1.8Ghz,那么可能是有问题的 查看 CPU 使用率,是否已经跑满了 –> 表现是 CPU 区域八个核心上,任务和任务之间没有空隙 查看是否低内存 应用进程状态有大量的 Uninterruptible Sleep | WakeKill - Block I/O HeapTaskDeamon 任务执行频繁 kswapd0 任务执行频繁 SystemServer 进程区域 input 事件读取和分发是否有异常 –> 表现是 input 事件传递耗时,比较少见 binder 执行是否耗时 –> 表现是 SystemServer 对应的 Binder 执行代码逻辑耗时 binder 等 am、wm 锁是否耗时–> 表现是 SystemServer 对应的 Binder 都在等待锁,可以通过 wakeup 信息跟踪等锁情况,分析等锁是不是由于应用导致的 是否有应用频繁启动或者被杀 –> 在 Systrace 中查看 startProcess,或者查看 Event Log SurfaceFlinger 进程区域 dequeueBuffer 和 queueBuffer 是否执行耗时 –> 表现是 SurfaceFlinger 的对应的 Binder 执行 dequeueBuffer 和 queueBuffer 耗时 主线程是否执行耗时 –> 表现是 SurfaceFlinger 主线程耗时,可能是在执行其他的任务 Launcher 进程区域(冷热启动场景) Launcher 进程处理点击事件是否耗时 –> 表现在处理 input 事件耗时 Launcher 自身 pause 是否耗时 –> 表现在执行 onPause 耗时 Launcher 应用启动动画是否耗时或者卡顿 –> 表现在动画耗时或者卡顿 初步分析有怀疑的点之后 如果是系统的原因,首先需要看应用自身是否能规避,如果不能规避,则转给系统来处理 如果是应用自身的原因,可以使用 TraceView(AS 自带的 CPU Profiler)、Simple Perf 等继续查看更加详细的函数调用信息,也可以使用 TraceFix 插件,插入更多的 TraceTag 之后,重新抓取 Systrace 来对比分析 问题可能有很多个原因 首先要把影响最大的因素找出来优化,影响比较小的因素可以先忽略 有些问题需要系统的配合才能解决,这时候需要跟系统一起进行调优(比如各大 App 厂商就会有专门跟手机厂商打交道的,手机厂商会以 SDK 的形式,暴露部分系统接口给 App 来使用,比如 Oppo 、华为、Vivo 等) 有些问题影响很小或者无解,这时候需要跟测试同学沟通清楚 有些问题是重复问题或不同平台的相同,可以在 Bug 库中搜索是否有案例 帮我总结以上systrace中分析响应速度问题的过程,给我形成一个大致的思路和流程,给我讲明白
最新发布
03-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值