2013-02-20 122 views
9

我有2個進程(A,B)共享相同的互斥體(使用WaitForSingleObject/ReleaseMutex調用)。一切工作正常,但當進程A崩潰時,進程B快樂地嗡嗡作響。當我重新啓動進程A時,存在死鎖。Win32當進程崩潰時,不會釋放互斥體

深入調查顯示進程B在進程A崩潰後可以成功調用ReleaseMutex()兩次。

我的解釋:在進程A崩潰後,互斥鎖仍然被鎖定,但互斥量的所有權很容易轉移到進程B(這是一個錯誤)。這就是爲什麼它快樂地嗡嗡聲,調用WaitForSingleObject(返回WAIT_OBJECT_0)和ReleaseMutex(返回TRUE)。

是否有可能使用與Mutex類似的命名同步原語,使得進程A中的崩潰將釋放互斥鎖?

一個解決方案是使用SEH並捕獲崩潰並釋放互斥鎖,但我真的希望Windows有一個強大的基元,在進程崩潰時不會出現死鎖。

+2

這可能是一個有趣的文章,供您閱讀:http://blogs.msdn.com/b/oldnewthing/archive/2005/09/12/463977.aspx – 2013-02-20 16:52:32

回答

24

,你必須在這裏做一個關於如何互斥適用於Windows的一些基本假設:

  • 一個互斥體是一個操作系統對象的引用計數。它不會消失,直到互斥的最後一個句柄被關閉
  • 剩下的未關閉的進程終止時由操作系統關閉任何手柄,遞減引用計數
  • 一個互斥重入,調用WaitForSingleObject的在同一線程上的互斥體上成功並需要用相同數量的ReleaseMutex調用進行平衡
  • 擁有它的線程終止時沒有調用ReleaseMutex,擁有的互斥體將變爲廢棄。在此狀態下在互斥體上調用WaitForSingleObject會生成WAIT_ABANDONED錯誤返回碼
  • 它絕不是操作系統中的錯誤。

所以你可以從你觀察到的結果中得出結論。當A崩潰時,互斥體沒有任何反應,B仍然有處理它。唯一可能的方式是B可以注意到A崩潰的原因是A在擁有互斥鎖時崩潰了。因爲B會死鎖,所以很容易觀察到這種情況。更有可能的是,B將會愉快地運行,因爲它現在完全沒有阻塞,沒有其他人會再獲得互斥。

此外,當A開始後會發生死鎖,證明您已經知道某事:B由於某種原因永久擁有互斥鎖。可能是因爲它遞歸獲取了互斥鎖。你知道這一點是因爲你注意到你必須給ReleaseMutex打電話兩次。這是您需要修復的錯誤。

您需要保護自己免受崩潰的兄弟進程,並且您需要爲此編寫明確的代碼。調用兄弟上的OpenProcess來獲取過程對象的句柄。當進程終止時,句柄上的WaitForSingleObject調用將完成。

+4

對於「這絕不是操作系統中的錯誤」。 :p – Deanna 2013-02-21 10:09:44

+0

對不起,我沒有把這個標記爲答案,但是......晚得再好,永遠不會。 謝謝,我不知道被遺棄國家的含義。 – 2017-11-26 04:03:27

9

如果持有互斥鎖的進程崩潰,那麼它就會被放棄。這取決於其他應用程序如何處理從等待函數返回的狀態。

如果它得到WAIT_ABANDONED,那麼它可以繼續進行,就好像所有的都是好的(大概是現在所做的)或「潛在不穩定的數據,謹慎行事」。 所有權不會自動傳遞給其他進程。

+10

我的猜測是進程B收到'WAIT_ABANDONED'並認爲它意味着'WAIT_FAILED'(而不是「以一種意想不到的方式成功」),所以它試圖再次獲得互斥體。 – 2013-02-20 17:44:20