今天下午我遇到了一些棘手的問題,因爲在mips64
上編譯程序,經常出現程序編譯不出來,或者運行不正常,花了很長的時間定位,最後和同事一些解決了,下面分享出來我提煉出來的一些核心定位問題的步驟。
子線程創建不出來
猜測:go
的程序都能創建出子線程,但是c++
的創建不出來,但是在 x86 可以,是不是什麼 linux 系統限制?
解決方法:加錯誤日誌進行調試(最 lower 辦法)
找到報錯點:
查詢 man
手冊,看看是不是能找到有幫助的東西
man pthread_attr_setstacksize
打印出解釋
ERRORS
pthread_attr_setstacksize() can fail with the following error:
EINVAL The stack size is less than PTHREAD_STACK_MIN (16384) bytes.
On some systems, pthread_attr_setstacksize() can fail with the error EINVAL if stacksize is not a multiple of the system page size.
翻譯上面的話,可能會產生這個錯誤
-
EINVAL
堆棧大小小於PTHREAD_STACK_MIN(16384)
字節。 -
在某些系統上,如果
stacksize
不是系統頁面大小的倍數,pthread_attr_setstacksize()
可能會失敗,並顯示錯誤EINVAL
查詢 linux
報錯碼含義, 得知錯誤碼 22
果然和 man
手冊中說的一致,是參數有問題。
第一次嘗試:擴大線程棧到上面說的 16384
,但還是報錯
根據經驗,查看最小頁大小,發現是 16k
, 而 x86
架構是 4K
,原來用的 20K
是不對齊的,怪不得創建不出來線程。
依次嘗試, 最終發現 10*16K
子線程成功創建。
但是不準確,按其說法,應該是設置 PAGESIZE
的整數倍都行,懷疑其對最小值有要求。 c++
的頭文件在 /usr/include
目錄下面, PTHREAD_STACK_MIN
是一個常量,估計裏面會有定義,嘗試查找
$ grep -rl PTHREAD_STACK_MIN *
bits/local_lim.h
pthread.h
還真讓我找到了, 根據英文註釋,至少要兩個 64K
作爲線程棧,才能跑起一個線程。
至此問題解決。
部分線程卡住
我發現程序雖然正常運行,但是部分功能不正常,經過查看日誌發現,有一個線程只執行了一半就卡住了。
經過查看日誌可以定位出是哪個線程卡住,如果從日誌看不出來也沒關係。可以使用 pstack 進程號
看一些進程堆棧。
查看進程 pid
ps -ef |grep 進程名
使用 gdb
查看是否出現問題,兩個重要命令
gdb attach {pid} #查看正在運行程序的棧
info thread #進入以後使用,查看線程信息
找到錯誤位置,出現了 fgets()
和 read()
函數,懷疑是此處出現問題。
懷疑 1: _LINE_LENGTH 1024
長度太短,接受命令返回值後超過了數組本身的長度,覆蓋了位置的內存。
這種情況我以前遇到過,表現應該是程序直接就崩潰了。
懷疑 2:執行命令的時候卡了,導致後面的程序沒有執行。
根據 gdb
打印出來的參數,執行 linux
命令進行測試,果然是卡在這了!
再次使用 pstree -p {pid}
查看,確實主線程,調用了 linux
命令卡住。
接下來解決卡命令的問題
解決 1:加 timeout
處理空返回。下面是示例命令,並不是我使用的命令。
timeout 5 ls -al
代表超過 5 秒返回。
解決 2:定位爲什麼這個 linux
命令會卡住。
strace ls -al
直到解決爲止。這就是今晚我加班到 10 點 30 解決的問題,我又用了一個小時總結下整個過程備忘,希望對你也有幫助。