您好,登錄后才能下訂單哦!
這篇文章主要講解了“怎么解決在feature/query分支上,在community倉庫,執行以下腳本,出現Crash問題”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“怎么解決在feature/query分支上,在community倉庫,執行以下腳本,出現Crash問題”吧!
在feature/query分支上,在community倉庫,執行以下腳本,出現Crash。
./test.sh -f general/parser/col_arithmetic_operation.sim
我登錄到指定的機器,查看了 core dump, 確實如此。Call Stack 截圖如下:
第一步:看哪個地方 crash。是 shash.c:250 行,使用 GDB 命令 “f 1″ 查看 stack 1,查看*pObj,一下就看到 hashFp 為 NULL,自然會 crash。但為什么會設置為空?其他參數呢?dataSize 設為 0 也一定是錯的。因此可以斷定,這個結構體是不對的。我們需要看上一層調用是否傳入了正確的參數。
第二步:使用 GDB “f 2″查看 stack 2,rpcMain.c:605 行,查看*pRpc,這些結構體里的參數顯得很正常,包括指向 hash 的指針值看不出有什么問題。那因此可以斷定調用是 OK 的,調用 taosGetStrHashData 應該提供了正確的參數。
第三步:既然參數對的,看 shash.c 的程序,那只可能是 SHashObj 這個結構體已經被釋放,訪問的時候,自然無效。再看代碼,只有一個可能,函數 taosCleanUpStrHash 被調用,因此我在改函數里馬上加上一行打印日志(注意 TDengine 的日志輸出控制,系統配置文件 taos.cfg 里參數 asyncLog 要設置為 1,否則 crash 時,有可能日志不打印出來)。重新運行腳本,查看日志,發現 taosCleanUpStrHash 沒有被調用過。那么現在只有一個可能,這一塊數據的內存被其他線程寫壞。
第四步:萬幸,我們有很棒的運行時內存檢查工具 valgrind, 可以通過運行它來找找蛛絲馬跡。一運行(valgrind 有很多選項,我運行的是 valgrind –leak-check=yes –track-origins=yes taosd -c test/dnode1/cfg),一下就發現有 invalid write,截圖如下:
第五步 :一看 valgrind 輸出,就知道 rpcMain.c:585 有 invalid write, 這里是 memcpy。從編碼上來看,這應該沒有問題,因為拷貝的是固定大小的結構體 SRpcConn,每次運行到這里都會執行的。那么唯一的可能就是 pConn 指向的是無效的內存區,那 pConn 怎么可能是無效的?我們看一下程序:
看 584 行,pConn = pRpc->connList + sid。這個 sid 是 taosAllocateId 分配出來的。如果 sid 超過 pRpc->sessions,那 pConn 毫無疑問就指向了無效的區域。那怎么確認呢?
第六步:加上日志 578 行,分配出的 ID 打印出來,編譯,重新運行測試腳本。
第七步:crash,看日志,可以看到 sid 能輸出到 99(max 是 100),還一切正常,但之后就崩潰。因此可以斷言,就是由于分配的 ID 超過了 pRpc→session。
第八步:查看分配 ID 的程序 tidpool.c,一看就知道原因,ID 分配是從 1 到 MAX,而 RPC 模塊只能使用 1 到 Max-1。這樣當 ID 返回為 max 時,RPC 模塊自然會產生 invalid write。
既然知道原因,那就很好辦,有兩套方法:
1. 在 tidpool.c,taosInitIdPool 里,將 maxId 減一,這樣分配的 ID 只會是 1 到 max-1。
2. 在 rpcMain.c 的 rpcOpen() 函數里,將
pRpc->idPool = taosInitIdPool(pRpc->sessions);
改為
pRpc->idPool = taosInitIdPool(pRpc->sessions-1);
如果應用要求最多 100 個 session,這么改,RPC 至多創建 99 個,為保證 100 個,再將
pRpc->sessions = pInit->sessions;
改為
pRpc->sessions = pInit→sessions+1;
兩種方法,都重新編譯,運行測試腳本通過,crash 不再發生。
遇到內存被寫壞的場景,一定要用 valgrind 跑一次,看是否有 invalid write。因為它是一個動態檢查工具,報的錯誤都應該是對的。只有把 invalid write 先解決,再去看 crash 問題。
這個 BUG 的核心是由于 tidpool.c 分配的 ID 范圍 是 1 到 max,而 RPC 模塊假設的 ID 分配是 1 到 max-1。因此是模塊之間的約定出了問題。
感謝各位的閱讀,以上就是“怎么解決在feature/query分支上,在community倉庫,執行以下腳本,出現Crash問題”的內容了,經過本文的學習后,相信大家對怎么解決在feature/query分支上,在community倉庫,執行以下腳本,出現Crash問題這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。