使用Windbg分析多線程死鎖項目實戰問題分享

目錄

1、問題描述

2、使用.effmach x86命令切換到32位上下文

3、切換到UI線程,發現UI線程死鎖了

4、使用!locks命令查看臨界區鎖的詳細信息,遇到了問題

5、使用dt命令查看臨界區對象信息,找到發生死鎖的多個線程

6、用戶態鎖與內核態鎖

7、最后


C++軟件異常排查從入門到精通系列教程(核心精品專欄,訂閱量已達8000多個,歡迎訂閱,持續更新...)https://blog.csdn.net/chenlycly/article/details/125529931C/C++實戰專欄(重點專欄,專欄文章已更新500多篇,訂閱量已達6000多個,歡迎訂閱,持續更新中...)https://blog.csdn.net/chenlycly/article/details/140824370C++ 軟件開發從入門到實戰(重點專欄,專欄文章已更新300多篇,歡迎訂閱,持續更新中...)https://blog.csdn.net/chenlycly/category_12695902.htmlVC++常用功能開發匯總(專欄文章列表,歡迎訂閱,持續更新...)https://blog.csdn.net/chenlycly/article/details/124272585C++軟件分析工具從入門到精通案例集錦(專欄文章,持續更新中...)https://blog.csdn.net/chenlycly/article/details/131405795開源組件及數據庫技術(專欄文章,持續更新中...)https://blog.csdn.net/chenlycly/category_12458859.html網絡編程與網絡問題分享(專欄文章,持續更新中...)https://blog.csdn.net/chenlycly/category_2276111.html? ? ? ?最近項目中又遇到了多線程死鎖的問題,導出了dump文件,事后用Windbg詳細分析了一下。本文詳細講述一下這個多線程死鎖問題的完整分析與排查過程,以供借鑒或參考。

1、問題描述

? ? ? ?測試同事在測試新版本軟件(新需求迭代,開發了新版本),問題軟件終端以SIP協議入會,會議中發起桌面共享,然后測試同事去忙其他事情,20分鐘后點擊停止發送桌面共享,然后UI界面不能正常顯示,且窗口不可點擊,估計是UI線程卡死了。

? ? ? ?將Windbg附加到軟件進程上,切換到0號UI線程,查看函數調用堆棧,顯示線程卡在獲取臨界區鎖的接口上,所以可以確定是UI線程和其他線程發生死鎖卡死了。因為調試中的Windbg中輸入命令很卡,所以直接到Windows任務管理中導出了軟件進程的dump轉儲文件。因為當前軟件不是崩潰閃退,是多線程死鎖引發卡死,所以進程還在的,可以從任務管理器中導出dump文件。

? ? ? ?從Windows任務管理器中導出dump文件,是生成dump文件的方式之一,生成dump文件有多種方式。關于dump文件的分類以及生成dump文件的多種方式,可以查看我的文章:

【C++軟件調試技術】dump文件類型與dump文件生成方法詳解https://blog.csdn.net/chenlycly/article/details/144424512

2、使用.effmach x86命令切換到32位上下文

? ? ? ? 從任務管理器中導出的dump文件,用Windbg打開,默認是64位上下文,查看線程函數調用堆棧,顯示的堆棧不是正常的堆棧(堆棧中顯示的函數不是代碼中的函數接口),如下:

而我們的軟件是32位的,需要使用.effmach x86命令切換到32位上下文。切換后就可以看到正常的函數調用堆棧,可以看到代碼中調用的接口。

? ? ? ?關于使用Windbg分析dump文件的方法與一般步驟,此處不再贅述,可以查看我之前寫的文章:

使用Windbg分析dump文件定位軟件異常的方法與操作步驟https://blog.csdn.net/chenlycly/article/details/146005441? ? ? ?有時我們需要將Windbg附加到目標進程上進行動態調試,如何使用Windbg進行動態調試,可以查看我之前寫的文章:

使用Windbg調試目標進程排查C++軟件異常的一般步驟與要點分享https://blog.csdn.net/chenlycly/article/details/145826705

3、切換到UI線程,發現UI線程死鎖了

? ? ? ?因為UI界面卡死堵塞了,所以初步懷疑可能是UI線程發生死鎖了。當然導致線程卡死,也可能是代碼中發生死循環導致函數一直不返回引起的。于是使用~0s命令切換到UI線程,輸入kn查看UI線程的函數調用堆棧,如下:

從堆棧中可以看出,UI線程調用了RtlEnterCriticalSection要獲取臨界區鎖,然后最終卡在等待臨界區鎖的接口NtWaitForAlertByThreadId上了。


? ? ? ?在這里,給大家重點推薦一下我的幾個熱門暢銷專欄,歡迎訂閱:(博客主頁還有其他專欄,可以去查看)

專欄1:該精品技術專欄的訂閱量已達到10000多個,專欄中包含大量項目實戰分析案例,有很強的實戰參考價值,廣受好評!專欄文章持續更新中,已經更新到210篇以上!歡迎訂閱!)

C++軟件調試與異常排查從入門到精通系列文章匯總https://blog.csdn.net/chenlycly/article/details/125529931

本專欄根據多年C++軟件異常排查的項目實踐,系統地總結了引發C++軟件異常的常見原因以及排查C++軟件異常的常用思路與方法詳細講述了C++軟件的調試方法與手段詳細介紹分析C++軟件問題的常用分析工具,以圖文并茂的方式給出具體的項目問題實戰分析實例(詳細講述分析排查過程,很有實戰參考價值),帶領大家逐步掌握C++軟件調試與異常排查的相關技術,適合基礎進階和想做技術提升的相關C++開發人員!

考察一個開發人員的水平,一是看其編碼及設計能力,二是要看其軟件調試能力!所以軟件調試能力(排查軟件異常的能力)很重要,必須重視起來!能解決一般人解決不了的問題,既能提升個人能力及價值,也能體現對團隊及公司的貢獻!

專欄中的文章都是通過項目實戰總結出來的,包含大量項目問題實戰分析案例,有很強的實戰參考價值!專欄文章還在持續更新中,預計文章篇數能更新到300篇以上!

專欄2:(本專欄涵蓋了C++多方面的內容,是當前重點打造的專欄,訂閱量已達8000多個,專欄文章已經更新到500多篇,持續更新中...)

C/C++實戰進階(專欄文章,持續更新中...)https://blog.csdn.net/chenlycly/category_11931267.html

以多年的開發實戰為基礎,總結并講解一些的C/C++基礎與項目實戰進階內容,以圖文并茂的方式對相關知識點進行詳細地展開與闡述!專欄涉及了C/C++領域多個方面的內容,包括C++基礎及編程要點(模版泛型編程、STL容器及算法函數的使用等)、數據結構與算法C++11及以上新特性(開源代碼中可能會用到很多新特性(比如WebRTC開源庫),日常編碼中也會用到部分新特性,面試時也會頻繁地涉及到,學習新特性很有必要)、常用C++開源庫的介紹與使用(比如SQLite、libcurl、libwebsockets、libevent、jsoncpp/RapidJson、Redis、RabbitMQ、MongoDB、MQTT、ZooKeeper、OpenCV、FFmpeg、SDL、GStreamer、Live555、ReactOS等)、代碼分享(調用系統API、使用開源庫)、常用編程技術(動態庫、多線程、多進程、數據庫及網絡編程等)、軟件UI編程(Win32/duilib/QT/MFC)、C++軟件調試技術(引發C++軟件異常的常見原因分析與總結、排查C++軟件異常的手段與方法、分析C++軟件異常的基礎知識、使用常用軟件分析工具分析C++軟件問題、多個項目實戰問題分析案例分享等)、設計模式(單例模式、工廠模式、觀察者模式、狀態模式等)、網絡基礎知識與網絡問題分析進階內容(實戰問題分析實例分享)等。本專欄的內容都是建立在項目實踐的基礎上,來源于項目實戰,服務于項目實戰,很有實戰參考價值!

專欄3:??

C++常用軟件分析工具從入門到精通案例集錦匯總(專欄文章,持續更新中...)https://blog.csdn.net/chenlycly/article/details/131405795

常用的C++軟件輔助分析工具有SPY++、PE工具、Dependency Walker、GDIView、Process Explorer、Process Monitor、API Monitor、Clumsy、Windbg、IDA Pro等,本專欄詳細介紹如何使用這些工具去巧妙地分析和解決日常工作中遇到的問題,很有實戰參考價值!

專欄4:???

VC++常用功能開發匯總(專欄文章,持續更新中...)https://blog.csdn.net/chenlycly/article/details/124272585

將10多年C++開發實踐中常用的功能,以高質量的代碼展現出來。這些常用的高質量規范代碼,可以直接拿到項目中使用,能有效地解決軟件開發過程中遇到的問題。

專欄5:?

C++ 軟件開發從入門到精通(專欄文章,持續更新中...)https://blog.csdn.net/chenlycly/category_12695902.html

根據多年C++軟件開發實踐,詳細地總結了C/C++軟件開發相關技術實現細節,分享了大量的實戰案例,很有實戰參考價值。


4、使用!locks命令查看臨界區鎖的詳細信息,遇到了問題

? ? ? ?輸入kv命令,將堆棧中傳入的參數值打印出來,如下所示:

對于臨界區對象鎖,調用的是RtlEnterCriticalSection,傳入的是臨界區結構體CRITICAL_SECTION對象地址,所以UI線程等待的臨界區對象地址就是堆棧中的參數值087d89f0。

? ? ? ?于是輸入命令!locks,查看當前臨界區對象信息,看看087d89f0臨界區鎖被哪個線程占用了。輸入后提示:

提示沒法解析ntdll.dll庫中的RtlCriticalSectionList接口,應該是沒有設置系統pdb下載地址的問題。于是將微軟系統庫pdb在線下載地址srv*f:\mss0616*http://msdl.microsoft.com/download/symbols設置到windbg中,重新輸入!locks,結果還是提示有問題:

沒法讀取dump文件中的內存,當前dump文件中的內存數據不全?奇怪了,當前的dump文件是從資源管理器中導出的,應該是全dump文件,咋還沒法讀取內存呢?難道從正在調試的Windbg中導出的dump文件才是包含所有內存的dump文件?讓測試同事那邊把Windbg附加到程序進程中重新復現一下,然后從正在調試的Windbg中導出dump文件再分析一下?

? ? ? ?關于pdb符號文件以及如何使用pdb符號文件,可以查看我之前寫的文章:

【C++軟件調試技術】什么是pdb文件?如何使用pdb文件?哪些工具需要使用pdb文件?https://blog.csdn.net/chenlycly/article/details/140742876

5、使用dt命令查看臨界區對象信息,找到發生死鎖的多個線程

? ? ? ?既然!locks命令沒法查看到當前軟件進程中的臨界區對象信息,我們可以嘗試使用dt命令看一下。我們上面已經知道UI線程在等待臨界區鎖087d89f0(臨界區結構體CRITICAL_SECTION對象地址),可以使用“dt RTL_CRITICAL_SECTION 087d89f0”命令,把地址087d89f0當成RTL_CRITICAL_SECTION結構體對象的首地址,從而獲取到該地址對應的結構體對象的字段值,如下所示:

其中的OwningThread字段就是當前臨界區鎖被哪個線程占用了(還沒釋放)。因為占用該臨界區鎖的線程沒有釋放鎖,導致UI線程一直獲取不到鎖,一直在等待,產生死鎖。

? ? ? ?OwningThread字段值 0x00003bc8就是線程id,于是使用~*命令,將當前進程中的所有信息打印出來:

找到線程id為0x00003bc8的線程對應的線程號,對應38號線程。

? ? ? ?于是使用~38s命令,切換到38號線程,使用kn命令將該線程的函數調用堆棧打印出來,看看為什么占用了臨界區鎖087d89f0沒有釋放。38號線程的函數調用堆棧如下:

38號線程也卡住了,卡在NtWaitForSingleObject接口上,沿著調用堆棧向上看,是在等待mutex互斥量鎖。38號線占用了臨界區鎖087d89f0,因為38號線程在等待另一個mutex互斥量鎖,所以沒有釋放臨界區鎖087d89f0,所以導致UI線程一直拿不到臨界區鎖087d89f0產生了堵塞卡死。至于38號線一直在等待mutex互斥量鎖,肯定這個互斥量鎖被第三個線程占用了,導致38號線程卡死了。

6、用戶態鎖與內核態鎖

? ? ? ?本案例中涉及到的鎖有臨界區和mutex互斥鎖,前者是用戶態鎖,后者是內核態鎖。

? ? ? ?用于多線程之間同步的常用鎖有臨界區、事件、信號量和互斥量等,其中臨界區是Windows系統獨有的,是用戶態鎖,事件、信號量和互斥量則是內核態鎖。用戶態鎖在訪問時不需要進行用戶態與內核態的切換,效率比較高。對于內核態鎖,訪問時要進行用戶態與內核態之間的切換,相對于用戶態鎖,訪問效率要低一些。我們的業務代碼運行在用戶態,當調用系統API訪問內核態鎖時,API函數底層需要從用戶態切換到內核態,訪問完后,再從內核態返回到用戶態,這就是用戶態與內核態之間的切換。

? ? ? ?出于訪問鎖的效率問題,一般在Windows平臺會優先使用臨界區鎖。在很多支持跨平臺的開源代碼中,封裝的鎖在Windows平臺上都被定義成臨界區鎖。

7、最后

? ? ? ? 所以本案例中應該是3個線程之間發生了死鎖。因為當前發生死鎖的多個線程屬于底層的音視頻編解碼模塊,所以這個問題的后續排查只能交給該模塊的開發團隊了,我這邊的排查工作就基本完成了。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/92758.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/92758.shtml
英文地址,請注明出處:http://en.pswp.cn/web/92758.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

防火墻組網方式總結

一、部署模式:靈活適配多樣網絡環境下一代防火墻(NGAF)具備極強的網絡適應能力,支持五種核心部署模式,可根據不同網絡需求靈活選擇。路由模式:防火墻相當于路由器,位于內外網之間負責路由尋址&a…

AI大模型:(二)5.1 文生視頻(Text-to-Video)模型發展史

目錄 1.介紹 2.發展歷史 2.1.早期探索階段(2015-2019) 2.1.1.技術萌芽期 2.1.2.RNN/LSTM時代 2.2.技術突破期(2020-2021) 2.2.1 Transformer引入視頻生成 2.2.2 擴散模型的興起 2.3.商業化突破期(2022-2023) 2.3.1 產品化里程碑 2.3.2 競爭格局形成 2.4.革命…

14mm尋北儀能否塞進液壓支架生死縫隙?

在煤礦井下世界的方寸之間,液壓支架的每個關鍵節點都承載著千鈞重壓。頂梁鉸接點、立柱頂端、掩護梁角落,恰恰是空間最為局促的“禁區”。ER-MNS-10A MEMS尋北儀應運而生!它采用了先進的MEMS陀螺技術,以14mm至薄高度、40g極致輕盈…

python之淺拷貝深拷貝

文章目錄潛拷貝(shallow copy)深拷貝(deep copy)總結一下python的淺拷貝和深拷貝.潛拷貝(shallow copy) python中潛拷貝指的是:構造一個新的復合對象,然后將原對象中的對象引用插入其中 平常開發過程中潛拷貝是比深拷貝更常見的場景. 比如編程中使用到的一些基本的…

普通大學本科生如何入門強化學習?

問題:你平時是如何緊跟大型語言模型和智能體技術前沿的?有哪些具體的學習和跟蹤方式?回答:我會通過“輸入-內化-實踐”結合的方式跟蹤前沿。首先,學術動態方面,每天花10分鐘瀏覽arXiv的http://cs.CL和http://cs.AI板塊&#xff0c…

新手向:Python實現數據可視化圖表生成

Python數據可視化入門:從零開始生成圖表數據可視化是數據分析過程中不可或缺的關鍵環節,它通過將抽象的數字信息轉化為直觀的圖形展示,幫助分析師和決策者更快速、更準確地發現數據中隱藏的模式、規律和發展趨勢。在當今大數據時代&#xff0…

VBA即用型代碼手冊:計算選擇的單詞數Count Words in Selection

我給VBA下的定義:VBA是個人小型自動化處理的有效工具。可以大大提高自己的勞動效率,而且可以提高數據的準確性。我這里專注VBA,將我多年的經驗匯集在VBA系列九套教程中。作為我的學員要利用我的積木編程思想,積木編程最重要的是積木如何搭建及…

DNS(域名系統)

分層結構根域名(ipv4,13臺),二級域名,三級域名……相關記錄A將域名解析為ipv4地址AAAA將域名解析為ipv6地址MX指名該區域為郵件服務區PTR反向查詢將主機名解析為域名NS記錄服務器的名字CNAME別名查詢方式遞歸查詢迭代查…

【大模型】強化學習算法總結

角色和術語定義 State:狀態Action:動作Policy/actor model:策略模型,用于決策行動的主要模型Critic/value model:價值模型,用于評判某個行動的價值大小Reward model:獎勵模型,用于給…

基于梅特卡夫定律的開源鏈動2+1模式AI智能名片S2B2C商城小程序價值重構研究

摘要:梅特卡夫定律揭示了網絡價值與用戶數量的平方關系,在互聯網經濟中,連接的深度與形式正因人的參與發生質變。本文以開源鏈動21模式、AI智能名片與S2B2C商城小程序的協同應用為研究對象,通過實證分析其在社群團購、下沉市場等場…

Ubuntu22.04安裝CH340驅動及串口

一、CH340驅動安裝 1.1 查看USB設備能否被識別 CtrlAltT打開終端: lsusb 插入設備前: 插入設備后: 輸出中包含ID 1a86:7523 QinHeng Electronics CH340 serial converter的信息,這表明CH340設備已經被系統識別。 1.2 查看USB轉串…

CPU緩存(CPU Cache)和TLB(Translation Lookaside Buffer)緩存現代計算機體系結構中用于提高性能的關鍵技術

CPU緩存(CPU Cache)和TLB(Translation Lookaside Buffer)緩存是現代計算機體系結構中用于提高性能的關鍵技術。它們通過減少CPU訪問數據和指令的延遲來提高系統的整體效率。以下是對這兩者的詳細解釋: 1. CPU 緩存 CPU…

唐揚·高并發系統設計40問

課程下載:https://download.csdn.net/download/m0_66047725/91644703 00開篇詞 _ 為什么你要學習高并發系統設計?.pdf 00開篇詞丨為什么你要學習高并發系統設計?.mp3 01 _ 高并發系統:它的通用設計方法是什么?.pdf …

基于Spring Data Elasticsearch的分布式全文檢索與集群性能優化實踐指南

基于Spring Data Elasticsearch的分布式全文檢索與集群性能優化實踐指南 技術背景與應用場景 隨著大數據時代的到來,海量信息的存儲與檢索成為各類應用的核心需求。Elasticsearch 作為一款分布式搜索引擎,憑借其高可擴展、高可用和實時檢索的優勢&#x…

Linux系統編程——基礎IO

一些前置知識:文件 屬性 內容文件 分為 打開的文件、未打開的文件打開的文件:由進程打開,本質是 進程與文件 的關系;維護的文件對象先加載文件屬性,文件內容一般按需加載未打開的文件:在永久性存儲介質 —…

力扣164:最大間距

力扣164:最大間距題目思路代碼題目 給定一個無序的數組 nums,返回 數組在排序之后,相鄰元素之間最大的差值 。如果數組元素個數小于 2,則返回 0 。 您必須編寫一個在「線性時間」內運行并使用「線性額外空間」的算法。 思路 這道題的思路…

Redis類型之Hash

1.hash常用操作 這里還是要強調,redis的類型指的是value的類型。故而這里的hash是把key這一層組織完成以后,到了value這一層,value的其中一種類型還可以是hash。1.1 HSET 和 HGETHSET:設置hash類型的keyHSET key field value [fie…

Apache Pulsar性能與可用性優化實踐指南

Apache Pulsar性能與可用性優化實踐指南 一、技術背景與應用場景 隨著微服務、實時計算和大數據平臺的普及,消息系統承擔了海量數據的傳輸與解耦任務。Apache Pulsar作為新一代分布式消息與流處理系統,擁有多租戶、持久化存儲和靈活一致性的特點&#xf…

工單分類微調訓練運維管理工具原型

簡述需求進展之前,我嘗試用Longformer模型來訓練工單分類系統,但問題很快就暴露出來:Longformer訓練時間長得讓人抓狂,每次訓練只能針對一個租戶的數據,無法快速適配多個租戶的需求。切換一個使用相同標簽的租戶還能夠…

@CacheConfig??當前類中所有緩存方法詳解

CacheConfig??當前類中所有緩存方法詳解在 Spring Cache 抽象中,CacheConfig 是一個??類級別注解??,用于為??當前類中的所有緩存方法(如 Cacheable、CachePut、CacheEvict)提供默認配置??。其核心作用是??避免在每個方…