您好,登錄后才能下訂單哦!
問題最終的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; }
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。