一次QNX上進程死鎖排查

先有利器,纔好幹活

  1. 通過pidin加參數 %B,可以看到當前進程的各個線程的STATE,例如:NANOSLEEP, SEM, JOIN,SEND,REPLY, RECEIVE, MUTEX, CONDVAR, 等等。
  2. QNX系統好一點的是,能夠標明線程被鎖住的mutex的地址,mutex隸屬的線程,被鎖住的次數。還能標明自線程REPLY、SEND等STATE下,所依賴的對方線程號。

本次問題出現在

MessageQueue類中的 pushMessage 和 handleMessage 兩個方法公用一把鎖來保護成員變量m_queue。一個MessageQueue的pushMessage方法會在調用線程, handleMessage會在MessageQueue自有線程中使用。當handleMessage中被客戶端業務代碼阻塞後,push就會被阻塞;

  1. 因此我的服務端的三條線程,通過兩個MessageQueue, 兩套鎖, 關聯起來。
  2. 客戶端服務端通過qnx msg passing的同步機制,關聯起來;
  3. 客戶端通過同樣的MessageQueue類, 兩條線程的一套鎖,關聯起來;

最後,死鎖來了:

  1. 客戶端MessageQueue中自有線程中的handleMessage調用業務函數鎖住;
  2. 導致客戶端MessageQueue pushMessage 方法鎖住;
  3. 導致服務端的MsgSend 阻塞在REPLY狀態;
  4. 導致服務端兩個 MessageQueue ,三個線程鎖起來。

解決方法

客戶端

handleMessageQueue中copy一份msg,把並把鎖及時釋放,原msg對象及時銷燬,msg副本在客戶端使用完後銷燬。確保客戶端卡主,不影響服務端。

服務端

業務和代碼都可控,不需要msg copy。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章