一 总述
下面是一份dump 的log:
810 876 I system_server: libdebuggerd_client: started dumping process 678
740 740 I /system/bin/tombstoned: registered intercept for pid 678 and type kDebuggerdNativeBacktrace
678 678 I libc : Requested dump for tid 678 (cameraserver)
740 740 I /system/bin/tombstoned: received crash request for pid 678
740 740 I /system/bin/tombstoned: enqueueing crash request for pid 678
740 740 I /system/bin/tombstoned: found intercept fd 512 for pid 678 and type kDebuggerdNativeBacktrace
7840 7840 I crash_dump32: performing dump of process 678 (target tid = 678)
涉及到的模块有:
1 system_server
2 debuggerd
3 target_pid
4 crash_dump
5 debuggerd_client
6 tombstoned
1和2 system_server 和debuggerd都是调用的5 debuggerd_client 实现的。
二者区别:
system_server 可能是写到文件中的,如anr文件;
debuggerd是打印到标准输出上STDOUT_FILENO
3 target_pid 与4 crash_dump 是同一个code,3 target_pid会在fork出来一个进程(就是4 crash_dump)实现dump trace的功能
总体实现方法是:
1 各进程间的通信是使用socket实现的。
2 当建立socket 通信后,debuggerd_client会发送signal 给target_pid,target_pid使用signal catcher处理对应的signal信号,就是crash_dump逻辑了。
二 ANR触发dump trace信息
举例system server中的逻辑:抓anr的trace信息
watchdog里面会监控system server主要service的状态,如果发生anr就会监控到,然后调用ActivityManagerService.dumpStackTrace API,。
这个api中会有需要dump的进程信息,其中watchdog中指定dump的native 进程,ams 还会其他check的extra 进程。
然后for循环dump每个进程的trace信息。
ams>android_os_Debug>debuggerd_client.dump_backtrace_to_file_timeout>debuggerd_trigger_dump
这些API都是在system_server 进程中。
debuggerd进程的实现也依赖这个debuggerd_trigger_dump。
debuggerd_trigger_dump 就是在debuggerd_client中实现的了。后面再介绍。
三 tombstoned 进程
开机就会启动的进程,
创建三个socket:
constexpr char kTombstonedCrashSocketName[] = "tombstoned_crash";
constexpr char kTombstonedJavaTraceSocketName[] = "tombstoned_java_trace";
constexpr char kTombstonedInterceptSocketName[] = "tombstoned_intercept";
1 tombstoned与debuggerd_client 的通信是使用socket "tombstoned_intercept"。
debuggerd_client 向tombstoned_intercept发送InterceptRequest 请求,tombstone中的intercept_manager 处理该请求,并返回intercept的状态,如register/started/failed等。
2 tombstoned 与crash_dump的通信使用socket “tombstoned_crash” 或“tombstoned_java_trace”,这个是根据dump的type决定的。
crash_dump建立联系后,向tombstoned发送kDumpRequest 请求,然后tombstoned返回kPerformDump,并同outputfd一块返回。
所以tombstoned逻辑中会有两个逻辑:一个是处理intercept(使用intercept_manager)另一个是处理crash_request.
四 crash_dump64 进程
这个是dump进程的东西,往dump进程中发送signal 信息,这边就会收到signal 信号,然后由signal 处理程序处理。
然后fork一个进程专门处理dump的功能。
在新进程中,
1与tombstoned 建立socket 通信,
2 发送kDumpRequest并等待kPerformDump。
3 dump的逻辑
4 通知dump conplete
五 总体流程
A tombstone 进程启动,创建好三个socket
B 各进程启动,加载signal catcher
C 出现anr情况, system server watchdog 逻辑monitor 问题,触发ams.dumpstacktrace
然后就是上图的流程了
复杂的是tombstoned的消息处理逻辑:
intercept msg使用InterceptManager
crash msg使用内部的crash和crashQueue
intercept_manager.cpp中 intercept_accept_cb/ intercept_request_cb / intercept_close_cb
tombstoned.cpp中 crash_accept_cb/crash_request_cb/ crash_completed_cb/perform_request
intercept_request_cb 处理与debuggerd_client的通信,接收request,发送register和started
crash_request_cb/perform_request 处理与crash_dump的通信,接收kDumpRequest/发送kPerformDump
perform_request 里面会check intercept_manager 中是否有匹配项,并将获取其outputfd。
当crash_dump将所有需要的堆栈信息获取到后,通知tombstone kCompletedDump
tombstone中由crash_completed_cb 接收complete消息,并打印写到什么文件中。
【注意outputfd】
如果是system server获取的anr信息,则outputfd是anr文件,是由debuggerd_client 通过socket传递给intercept_manager 中,保存在数组中。
在接收到dumpRequest命令后,tombstone会check intercept数组,获取到对应的outputfd,传递给crash_dump 进程中,所有的dump实现中都是直接写到这个outputfd中了。
如果是target _pid 自己出现的crash等信息,这个outputfd 就是在tombstoned中自己创建的,
perform_request > null = GetIntercept > CrashQueue::for_crash(crash.get())->get_output(crash->crash_type) > create_temporary_file
crash_completed_cb > crash_completed > rename_tombstone_fd > /data/tombstones/tombstone_00