写点什么

Android ANR 分析(trace 文件的产生流程中)

作者:北洋
  • 2022 年 6 月 08 日
  • 本文字数:1185 字

    阅读完需:约 4 分钟

接着分析最后一步向收集到的进程发送信号(Android5.0 之前是 dump 用的 SuspendAll 线程,收集信息之后用 ResumeAll 恢复。在 5.0 之后采用的是 checkPoint 进行 dump 信息)


发生 ANR 时,systemServer 进程会执行 dumpStackTraces 函数,在该函数中发 SIGQUIT 信号给对应的进程(上面有分析到)


处于安全考虑,进程之间是相互隔离的,即使系统进程也无法获取其他进程的信息,所以要借助于 IPC 通信,将指令发送到目标进程,目标进程接收到消息后,协助完成自身进程 Dump 信息并发送给系统进程。Android P 流程:



1.一个进程接收到了 SIGQIUT 信号的时候,SingaCatcher 线程的 WaitForSignal 函数会返回接着会调用到 HandlerSigQuit()函数。



2.hindleSigQuit()函数为:



3.DumpForSigQuit()函数:



这是读取的信息,但是什么时候去读取呢(什么时候才能保证获取到的却是是需要的东西,例如 GC 信息,当前分配了多少对象,这些打印一般都需要在 suspend 当前进程里面的所有的线程),接下来先分析这个 suspend 过程:



这个挂起 SupendAll 实在 Thread_list.cc 中实现的,他的作用就是用来 suspend 当前进程里面所有其他的线程(一般发生在 GC,DumpForSigQuit 等过程中)。SuspendAll 过程实现最重要的就是 ModifySupendCount(self,+1,false)这段语句他会修改对应 Thread 对象的 suspend 引用计数:



因为传入的 delta 值是+1 所以会先执行 AtmoicSetFlag()利用原子操作设置了 KSuspendRequest 标志位,代表当前这个线程有挂起请求。什么时候会进行检测这个标志位呢?这里涉及到了 checkPoint 的知识点最后讲解(在线程运行中进行上下文切换(例如 java 线程转换为 Native 线程)时就会运行 CheckSuspend 函数,这个函数才是真正的把当前线程 suspend:



可以看到检测到了 KSuspendRequest 标记就会执行 FullSuspend 函数,KSuspendRequest 标志位是用来 dump 线程的堆栈的,分析完了 SuspendAll 之后,再继续分析 FullSuspendCheck 函数:



调用 TransitionFromRunnableToSuspend()这个函数后,线程就进入了 KSuspended 状态,然后在调用 TransitionFromSuspendedToRunnablecpm 函数从 Suspend 状态切换到 Runnable 状态的时候会阻塞在一个条件变量上,除非调用 SuspendAll 的线程接着又调用了 ResumeAll()函数,要不然这些线程就会一直被阻塞住。


4.现在就把 SuspendAll 的流程分析完了,但是 dump 线程堆栈的时候并不是在设置了挂起标志位(KSuspendRequest)后执行的,与他相关的是另外一个标志位 KCheckpointRequest,接下来看一下 Thread_list 的 Dump 函数,这个函数会在 Thread_list 的 DumpForSigQuit 中会被调用到,也就是在 Signal Cathcer 线程处理 SIGQUIT 信号的过程中。



这个函数先创建了一个叫 DumpCheckPoint 对象 checkpoint,然后调用了 RunCheckpoint 将这个对象传入,这个函数会返回现在处于 Runnable 状态的线程个数,接着调用了 WaitForThreadsToRunThroughCheckpoint()等待这些处于 Runnable 的线程都执行完 DumpCheckpoint 的 Run 函数,如果等待超时就会报错。



发布于: 刚刚阅读数: 4
用户头像

北洋

关注

Android开发 2021.05.25 加入

记录Android学习之路 分享读书心得体会~

评论

发布
暂无评论
Android ANR 分析(trace 文件的产生流程中)_6月月更_北洋_InfoQ写作社区