我們監控平台有台報警伺服器,其主要功能是接收前端,tddc,網管伺服器等傳送的報警,並依據報警聯動配置進行相應的聯動操作,最近發現在該伺服器執行過程中,通過任務管理器檢視其控制代碼數量會不斷增加,以至於影響其他伺服器工作,初步懷疑是控制代碼洩露問題,現對其進行分析排查。
控制代碼是windows用來標識應用程式所建立或使用的物件的唯一整數,windows的核心物件包括進執行緒,視窗,位圖,gdi物件等等。應用程式通過控制代碼訪問核心物件,當使用完核心物件之後需要釋放資源關閉該核心物件控制代碼,如果未能正確關閉,則會造成控制代碼洩露。
一般而言,如果懷疑發生了控制代碼洩露,最首要任務是查詢洩露的控制代碼型別,這樣有助於後面的排查分析,縮小目標範圍。這時可以通過一些輔助工具來幫助分析,如process explorer,pchunter等,這些工具能夠非常明了的看到程序所正在使用的核心物件,可以幫助我們找到問題所在。
開啟process explorer,找到執行的報警伺服器程序,該工具的會顯示出報警伺服器當前建立的核心物件控制代碼,如圖,可以看出該程序的控制代碼數已經有上千個,而且還在快速增長中。
該工具很方便的一點是,當有新的核心物件建立時,在下方的列表框中會以綠色標識出來,方便檢視,觀察一段時間發現,不停的有執行緒物件建立,而且不會關閉,初步猜測應該是執行緒物件的控制代碼沒有關閉導致。接下來的工作就是要找出這個執行緒核心物件在哪兒建立的。
查詢控制代碼的建立位置的可以通過windbg來獲取,windbg是windows下一款非常強大的核心偵錯程式。使用windbg的!htrace命令可以除錯控制代碼洩露。其原理比較簡單,就是分別為程序的核心物件做兩次快照,比較這兩次的不同,就可以知道有哪些核心物件建立了,同時還能找到是在哪兒分配的。
開啟windbg,按f6,附加報警伺服器程序。在命令列裡面輸入!htrace–enable開啟htrace功能。輸入!htrace –snapshot做第乙個快照,然後輸入g命令,讓程式執行一段時間。
該過程如下圖所示:
程式執行一段時間後,按ctrl+break鍵,將程式中斷下來。這時輸入!handle –diff,可以比較新增控制代碼的分配上下文。
通過仔細觀察,可以看出,有建立了多個執行緒核心物件,檢視乙個核心物件的資訊可以使用!handle命令。例如檢視handle值為f98的執行緒核心物件,可輸入!handlef98 ff。如下圖所示
其起始位址為hpr_getnetworkflowdata,可以確定該執行緒是使用hpr庫建立的,可以通過在源**中查詢hpr_thread_create來縮小範圍。
再圖中還可以看到執行緒id為7670.fef4,其中7670為程序id,fef4是執行緒id,因此可以切換到該執行緒看看,輸入
~~[fef4]s命令,切換執行緒。
出現了一條錯誤資訊,即該執行緒已經不存在了,那其實我們就基本可以確定這裡發生了洩露,執行緒已經不復存在,但該執行緒的核心物件卻未能關閉。
通過仔細觀察,我們可以看到這些執行緒物件都是同乙個執行緒建立的,如圖
最終都指向了71a8這個執行緒,這樣我們可以確定是71a8這個執行緒建立了很多執行緒核心物件,卻沒有將核心物件的控制代碼關閉,這樣造成了執行緒核心物件的控制代碼洩露,只要定位到71a8這個執行緒,就能找到洩露的地方。
輸入~~[71a8]s,切換到這個執行緒,並輸入kb列印其呼叫棧,如下圖:
呼叫棧是一堆非常奇怪的資料,其實是因為我的系統是64位的,而報警伺服器這個程序是32位的,windbg使用64位的上下文去解析32位的程序,造成了錯誤的解析。這時可以通過!sw這條命令來切換至32位的上下文。然後再敲入kb命令,就能看到該執行緒的呼叫棧了,如圖:
可以清楚的看到該執行緒的呼叫棧,此時該執行緒正在等待socket連線,使用的是hpr庫的hpr_accept函式,到這個地步,在源**中定位該執行緒函式就非常容易了。
在源**中搜尋hpr_accept函式,只有乙個地方:
可以清楚的看到,這個執行緒接受到連線之後,就建立了乙個執行緒,不過卻未將建立執行緒的控制代碼關閉,從而造成了控制代碼洩露,這與我們之前分析的一致。知道了問題所在,修改也就很方便了。
平台伺服器控制代碼洩露問題的排查與解決
我們監控平台有台報警伺服器,其主要功能是接收前端,tddc,網管伺服器等傳送的報警,並依據報警聯動配置進行相應的聯動操作,最近發現在該伺服器執行過程中,通過任務管理器檢視其控制代碼數量會不斷增加,以至於影響其他伺服器工作,初步懷疑是控制代碼洩露問題,現對其進行分析排查。控制代碼是windows用來標...
排查伺服器的問題
伺服器出現了問題,比如首先懷疑是nginx的bug,這時候就要看一下nginx的錯誤日誌 要找到錯誤日誌存放的位置,在根目錄下輸入 find name nginx.conf 找到nginx.conf的存放路徑,比如是 usr local openresty nginx conf nginx.conf...
如何排查Linux伺服器崩潰的問題
眾所周知,linux伺服器以可靠著稱。在企業環境中偶爾的系統崩潰可能看起來影響不是很多,但是準確地診斷系統故障的原因是必須的,因為系統故障可以明顯影響潛在的軟體或硬體問題指標。儘管故障診斷非常艱鉅,但通過使用本指南中提到的工具,您可以確保你能夠應對各種艱難的挑戰。因為每個伺服器都是不同的,本指南並非...