unix上防止程序死鎖的一些手段
在unix上做C的開發已經快2年了,一直在我們部門的一個主要產品項目組工作,該產品在市場上經受了一年半的考驗,可以說已經是很成熟的產品了,該產品在大部分客戶那里一直穩定的運行,沒有任何問題,而在少數幾個客戶那里,時不時的出現整個系統的吊死,而且該問題沒有任何規律可尋,除了系統吊死時候,我們對整個系統用pstack進行所有進程堆棧的跟蹤記錄外,我們沒有任何其它線索,沒有系統崩潰時候產生的CORE,我們開始面對來自客戶強大的壓力。。。。我們幾乎喘不過起來,我們要給客戶提交故障報告,而這些故障報告的問題都是這一個問題,這個問題開始成為懸在我們頭上的一把利劍。
我開始被指派來解決這個問題。其實我們很早的就從進程的堆棧跟蹤里知道這個問題是死鎖問題,但是,它是怎么發生的那,我們幾乎排查了整個系統的代碼,但是一無所獲。。。
在今年大年初一的時候,我們的系統又一次出現了該問題,當接到我們維護工程師的電話的時候,我的心情非常的沉重,我沒有做到我作為一個程序員應有的職責,還是象往常一樣,除了進程堆棧跟蹤外,我沒有任何其它線索,我還是照例接收郵件,查看我們維護工程師發回來的堆棧跟蹤記錄,可能是過年放假在家里休息了一段時間的緣故,腦袋好像特別清醒,面對堆棧跟蹤記錄,結合源碼,我迅速的意識到造成死鎖的原因是經典的競態條件問題,是一個進程準備退出的時候,它會喚醒它里面的一個線程,該線程首先會獲得一個鎖,進行后續出來,然后解鎖退出,但是由于該進程的主線程沒有采用任何方式來等待該線程的退出,而是直接通過return的方式進行了退出,我們知道,當主線程退出的時候,操作系統會直接終止該進程里面的其它線程,不會留任何機會讓那個線程做退出處理。而那個線程可能恰恰剛剛獲的了鎖,而還沒來得及解鎖,就被扼殺了,于是就造成了其它進程或線程再加這個鎖的時候,就會被阻塞,系統死鎖問題也就浮現了出來。
當然,我知道了是競態條件問題造成了死鎖,就會通過pthread_join來同步等待那個線程退出,來消除這個競態條件,也就消除了死鎖,問題其實也就解決了。但是,我們有沒有辦法來消除由于一個鎖的owner沒有釋放該鎖,就死掉了,其它線程再加這個鎖的時候而造成的死鎖問題那?
關于上面這個問題,我曾經在chinaunix請教過很多人,有的人想通過一個網絡鎖(就是加鎖、解鎖都要訪問網絡上的一臺機器)來解決,但是這些方法都不成熟,也很復雜,也好像有高手對這個問題不屑。我通過搜集很多資料發現,原來解決這個問題非常的簡單,簡單的不能在簡單了。
在很多系統上,當一個鎖的owner沒有釋放該鎖,就退出了,那么默認的方式就是其它線程再去加這個鎖的時候,就會阻塞,造成死鎖。而通過不同的屬性初始化這個鎖,我們能夠改變這種默認的方式:
pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT);
pthread_mutexattr_setrobust_np(&mattr,PTHREAD_MUTEX_ROBUST_NP);
通過設置鎖的上面兩個屬性,我們就改變了默認的行為,當一個鎖的owner死掉后,其它線程再去加這個鎖的時候,不會被阻塞,而是通過返回值EOWNERDEAD來報告錯誤,那么你可以根據這個錯誤來進行處理:首先是應該調用pthread_mutex_consistent_np函數來恢復該鎖的一致性,然后調用解鎖pthread_mutex_unlock,接下來在調用加鎖,這樣該鎖的行為就恢復正常了。如果上面這個函數在恢復鎖的一致性時候沒有成功,那么你只需要調用解鎖函數就OK了,然后直接返回,而不要去調用加鎖函數,那么接下來的線程在調用加鎖函數的時候,會得到返回值ENOTRECOVERABLE,那么需要你做的就是調用pthread_mutex_destroy來destroy掉該鎖,然后重新用鎖的屬性和鎖的初始化函數來重新初始化該鎖。
上面的這些解決死鎖方式比較適合在系統中只有一個鎖的情況,如果系統的死鎖是由于多把鎖的資源互相等待而造成的,那么這種解決方式無能為力。。。
注:上面有一些函數后面有np后綴的,表示not portable,就是不可移值的意思,這些函數是一些系統自己實現的,而不是POSIX標準。
關鍵了:程序、系統、POSIX
新文章:
- CentOS7下圖形配置網絡的方法
- CentOS 7如何添加刪除用戶
- 如何解決centos7雙系統后丟失windows啟動項
- CentOS單網卡如何批量添加不同IP段
- CentOS下iconv命令的介紹
- Centos7 SSH密鑰登陸及密碼密鑰雙重驗證詳解
- CentOS 7.1添加刪除用戶的方法
- CentOS查找/掃描局域網打印機IP講解
- CentOS7使用hostapd實現無AP模式的詳解
- su命令不能切換root的解決方法
- 解決VMware下CentOS7網絡重啟出錯
- 解決Centos7雙系統后丟失windows啟動項
- CentOS下如何避免文件覆蓋
- CentOS7和CentOS6系統有什么不同呢
- Centos 6.6默認iptable規則詳解