笛里谁知壮士心,沙头空照征人骨。这篇文章主要讲述调查android logcat进程退出原因相关的知识,希望能为你提供帮助。
问题最终的logcat进程退出的原因是log buffer size设置过小导致,默认size为256KB, 将buffer size设置为4MB后,后面就再没有出现过logcat中断的情况; 修改的code就一行代码,但这个原因的调查过程确实不易,这里记录一二1、测试同事在android 8.0平台版本中经常遇到logcat进程中途退出的情况, 导致抓的logcat信息不全,给分析定位问题带来不便;2、基于出现的这种,进行分析logcat进程退出的可能性; 一,在logcat进程中断时,监听logcat进程的程序显示exit code[1]; 有时候在cmd终端窗口显示" unexpected EOF" ,查看logcat.cpp相关code, 看到是logcat进程的while循环中android_logger_list_read读取到的数据为0, logcat进程主动调用logcat_panic进程,logcat进程退出。 二,然后尝试跟踪logcat进程读取数据的code流程,最终发现关联的内容蛮多的, 有liblog、libsysutils、logd,主要是这三个模块; 分析这类问题的最大难点是logcat进程退出时,是没有相关logcat信息的,很难看到问题原因, 只能自己dup重定向标准输入输出或者将log打印kmsg模块中; 最终根据添加的调试信息和打印log确认与buffer size有关; 分析大致过程如下: 1、 在应用或者服务等进程 往logd中写入log量过大时(大于buffer size设置的2倍), logd会调用kickMe函数,这里面会去判断stats size即系统中实际需要占用的大小, 当大于2倍我们在init函数中设定的默认buffer size(64KB)时, Logd认为reader读取数据的速度过慢,会主动release_Locked函数尝试断开连接, 断开连接后会导致logd.reader.per线程while循环break退出; Logd.cpp -> kickMe函数部分代码: void LogBuffer::kickMe(LogTimeEntry* me, log_id_t id, unsigned long pruneRows) { if (stats.sizes(id) > (2 * log_buffer_size(id))) { // +100% // A misbehaving or slow reader has its connection // dropped if we hit too much memory pressure. me-> release_Locked(); 2、logd.reader.per线程线程退出后,会调用SocketListener监听类的SocketListener::release, logd开启的LogReader是继承自SocketListener,会调用到doSocketDelete, SocketClient相关联的decRef函数, mRefCount—减值后会调用到~SocketClient析构函数, 析构后会调用close(mSocket) 关闭SocketListener端的socket连接, 3、socketListener的socket连接端开后, LogReader中onDataAvailable中read函数读取不到数据, 返回值为0,LogReader是将log传递给logcat bool LogReader::onDataAvailable(SocketClient* cli) { static bool name_set; if (!name_set) { prctl(PR_SET_NAME, " logd.reader" ); name_set = true; } char buffer[255]; int len = read(cli-> getSocket(), buffer, sizeof(buffer) - 1); if (len < = 0) { android::prdebug(" LogReader-> onDataAvailable ,length:%d ! " , len); doSocketDelete(cli); return false; } 4、接着会导致liblog模块的logdRead的recv函数返回值ret为0 (省略一部分transport相关过程,里面还有一些转化步骤), static int logdRead(struct android_log_logger_list* logger_list, ret = recv(ret, log_msg, LOGGER_ENTRY_MAX_LEN, 0); e = errno; fprintf(stderr, " logdRead()-> receive ret :%d ^^^^^^^^^^^ " ,ret); 5、导致最终Logcat端进程的while循环中android_logger_list_read读取到的数据为0, logcat进程主动调用logcat_panic进程,logcat进程退出。 while (!context-> stop & & (!context-> maxCount || (context-> printCount < context-> maxCount))) { struct log_msg log_msg; int ret = android_logger_list_read(logger_list, & log_msg); if (!ret) { fprintf(stderr, " android_logger_list_read error ,ret:%d ! " , ret); logcat_panic(context, HELP_FALSE, " read: unexpected EOF! " ); break; }
【调查android logcat进程退出原因】
推荐阅读
- APP怎样进行本地存储和图片缓存?
- APP模板开发APP的优势有哪些?
- Springboot Application 集成 OSGI 框架开发
- 张其中两周暴涨54倍的EOS内存,背后的Dapp是如何进行产品设计的()
- Android中渐变图片失真的解决方案
- Trapping Rain Water
- Android开发工程师文集-提示框,菜单,数据存储,组件篇
- Android开发工程师文集-layout_weight讲解
- Android开发工程师文集-相关控件的讲解,五大布局