进程崩溃时未释放Win32命名互斥锁 [英] Win32 Named mutex not released when process crashes
问题描述
我有2个进程(A,B)共享同一个互斥锁(使用WaitForSingleObject/ReleaseMutex调用).一切正常,但是当进程A崩溃时,进程B会愉快地嗡嗡作响.重新启动进程A时,出现死锁.
I have 2 processes (A, B) sharing the same mutex (using WaitForSingleObject / ReleaseMutex calls). Everything works fine, but when process A crashes, process B is humming along happily. When I restart process A, there's a deadlock.
更深入的调查显示,进程B崩溃后,进程B可以成功调用两次ReleaseMutex().
Deeper investigation reveals that process B can successfully call ReleaseMutex() twice after process A crashes.
我的解释:进程A崩溃后,互斥锁仍然处于锁定状态,但是互斥锁的所有权很容易转移到进程B(这是一个错误).这就是为什么它愉快地嗡嗡作响,调用WaitForSingleObject(返回WAIT_OBJECT_0)和ReleaseMutex(返回TRUE)的原因.
My interpretation: After process A crashes, the mutex is still locked, but ownership of the mutex transfers readily to process B (which is a bug). That's why it's humming along happily, calling WaitForSingleObject (getting WAIT_OBJECT_0 in return) and ReleaseMutex (getting TRUE in return).
是否可以使用类似于Mutex的命名同步原语,使进程A中的崩溃将释放互斥锁?
Is it possible to use a named synchronization primitive similar to Mutex in such a way that a crash in process A will release the mutex?
一种解决方案是使用SEH捕获崩溃并释放互斥锁,但是我真的希望Windows具有一个健壮的原语,而不会像进程崩溃时那样死锁.
One solution is to use SEH and catch the crash and release mutex, but I really hope Windows has a robust primitive that doesn't deadlock like that on process crash.
推荐答案
您必须在此处对互斥锁在Windows上的工作方式进行一些基本假设:
Some basic assumptions you have to make here about how a mutex works on Windows:
- 互斥锁是引用计数的操作系统对象.直到互斥锁上的最后一个句柄关闭,它才会消失
- 在进程终止时任何未关闭的句柄都被操作系统关闭,从而减少了引用计数
- 互斥锁是可重入,在同一线程上的互斥锁上调用WaitForSingleObject成功,并且需要用相等数量的ReleaseMutex调用来平衡 当拥有互斥锁的线程在不调用ReleaseMutex的情况下终止时,
- 拥有的互斥锁将被放弃.在这种状态下在互斥锁上调用WaitForSingleObject会生成WAIT_ABANDONED错误返回代码
- 这绝不是操作系统中的错误.
- a mutex is an operating system object that's reference-counted. It will not disappear until the last handle on the mutex is closed
- any handle that's left unclosed when a process terminates is closed by the operating system, decrementing the reference count
- a mutex is re-entrant, calling WaitForSingleObject on a mutex on the same thread succeeds and needs to be balanced with an equal number of ReleaseMutex calls
- an owned mutex becomes abandoned when the thread that owns it terminates without calling ReleaseMutex. Calling WaitForSingleObject on a mutex in this state generates the WAIT_ABANDONED error return code
- it is never a bug in the operating system.
因此,您可以根据自己的观察得出结论.当A崩溃时,互斥体什么都没有发生,而B仍然有一个句柄. B能够注意到A崩溃的唯一可能方法是A在拥有互斥量时崩溃.这样做的可能性很小,很容易观察到,因为B会死锁.因为现在B完全不受阻碍,所以B会很乐意继续运行,没有其他人可以再获取互斥体了.
So you can draw conclusions from this by what you observed. Nothing happens to the mutex when A crashes, B still has an handle on it. The only possible way B can notice that A crashed is when A crashed while it owned the mutex. Very low odds for that and easily observed since B will deadlock. Far more likely is that B will happily motor on since it is now completely unobstructed, nobody else is going to acquire the mutex anymore.
此外,当A重新启动时出现死锁证明您已经知道:B由于某种原因永久拥有该互斥量.可能是因为它以递归方式获取了互斥量.您之所以知道这一点,是因为您发现必须两次致电ReleaseMutex.这是您需要修复的错误.
Furthermore, a deadlock when A starts back proves something you already knew: B owns the mutex permanently for some reason. Possibly because it acquired the mutex recursively. You know this because you noticed you had to call ReleaseMutex twice. This is a bug you need to fix.
您需要保护自己免受崩溃的兄弟进程的侵害,并且需要为此编写明确的代码.在同级上调用OpenProcess以获取流程对象的句柄.进程终止时,将完成对句柄的WaitForSingleObject调用.
You'll need to protect yourself against a crashing sibling process and you need to write explicit code for that. Call OpenProcess on the sibling to obtain a handle on the process object. A WaitForSingleObject call on the handle will complete when the process terminates.
这篇关于进程崩溃时未释放Win32命名互斥锁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!