問題背景:工作中遇到一個多線程進程有部分線程(包含主線程)像卡死一樣不再處理其他事件,就像無限期休眠了一樣
知識點:進程、線程、線程鎖、條件變量、socket
定位工具:strace、htop、gdb
問題分析:
由於進程還在,用htop查看進程的線程也都在,首先就是想看看每個線程當前處於什么狀態
用gdb工具查看主線程當前堆棧信息如下
可以看到主線程在調用了pthread_join 等待一個線程結束后就阻塞了,具體在等待什么,結合log上下文可以判斷出是在等待那個線程(這里根據不同的代碼不一樣,具體問題具體分析)
接着用gdb工具查看主線程等待要結束的線程的堆棧信息如下
從改線程堆棧信息看該線程停留在pthread_cond_timewait這里,貌似在等待事件或者超時,但一直沒有事件,查看超時時間為500ms,可是為什么一直沒超時呢?不知道為什么一直沒超時
用strace工具跟蹤該進程的系統調用和信號傳遞
第17行 5621是主線程,可以看到他在等待對應線程id 509 退出,第1行 509就是等待要退出的線程,從信息可以看出是在等資源0xd32c2c 等待超時是按系統實時時鍾,絕對時間來判斷的,2147483611就是要等待的秒數,轉換出來就是“2038-01-19 11:13:31”
這是要等到“2038-01-19 11:13:31”才會超時退出,太嚇人了,為什么這個超時時間會這么大呢?暫時還不清楚
查看log出問題時的上下文,發現系統時間發生了變化
問題大致猜出來,是由於系統時間被修改為了 1901年,導致的超時時間是未來的 2038年(猜是系統庫函數讀取不了1970年以前的時間導致,有待研究驗證)
解決方案:把線程條件變量的超時時間判斷改為用啟站的運行時間替換系統實時時鍾
注:該問題定位和以上記錄大部分都是參數網友已整理的資料,這里把部分重要的參考引用標注如下。另外,根據網友總結用運行時間會多觸發系統調用,可能增加cpu使用時間
參考網址:
https://man.linuxde.net/strace
https://blog.csdn.net/Javadino/article/details/2891399
http://man7.org/linux/man-pages/man2/futex.2.html
https://blog.csdn.net/qiuxin315/article/details/8961150
http://www.matools.com/timestamp
https://linux.die.net/man/3/pthread_condattr_setclock
https://www.cnblogs.com/fallenmoon/p/8891218.html
https://www.cnblogs.com/hushaojun/p/7990951.html
https://www.cnblogs.com/raymondshiquan/articles/gettimeofday_vs_clock_gettime.html