调查android logcat进程退出原因

笛里谁知壮士心,沙头空照征人骨。这篇文章主要讲述调查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进程退出原因】


    推荐阅读