网站建设资讯

NEWS

网站建设资讯

调查androidlogcat进程退出原因-创新互联

问题最终的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 !\n", 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  ^^^^^^^^^^^\n",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 !\n", ret);
            logcat_panic(context, HELP_FALSE, "read: unexpected EOF!\n");
            break;
        }

创新互联公司专注为客户提供全方位的互联网综合服务,包含不限于成都网站建设、成都网站设计、芮城网络推广、微信平台小程序开发、芮城网络营销、芮城企业策划、芮城品牌公关、搜索引擎seo、人物专访、企业宣传片、企业代运营等,从售前售中售后,我们都将竭诚为您服务,您的肯定,是我们大的嘉奖;创新互联公司为所有大学生创业者提供芮城建站搭建服务,24小时服务热线:13518219792,官方网址:www.cdcxhl.com

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


分享文章:调查androidlogcat进程退出原因-创新互联
分享URL:http://cdweb.net/article/dejsgh.html