Win32当进程崩溃时,不会释放互斥体

问题描述:

我有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

,你必须在这里做一个关于如何互斥适用于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

如果持有互斥锁的进程崩溃,那么它就会被放弃。这取决于其他应用程序如何处理从等待函数返回的状态。

如果它得到WAIT_ABANDONED,那么它可以继续进行,就好像所有的都是好的(大概是现在所做的)或“潜在不稳定的数据,谨慎行事”。 所有权不会自动传递给其他进程。

+10

我的猜测是进程B收到'WAIT_ABANDONED'并认为它意味着'WAIT_FAILED'(而不是“以一种意想不到的方式成功”),所以它试图再次获得互斥体。 – 2013-02-20 17:44:20