winapi - 进程崩溃时未释放 Win32 命名互斥锁

标签 winapi win32-process

我有 2 个进程(A、B)共享相同的互斥锁(使用 WaitForSingleObject/ReleaseMutex 调用)。一切正常,但是当进程 A 崩溃时,进程 B 正在愉快地嗡嗡作响。当我重新启动进程 A 时,会出现死锁。

更深入的调查显示,在进程 A 崩溃后,进程 B 可以成功调用 ReleaseMutex() 两次。

我的解释:进程 A 崩溃后,互斥锁仍然被锁定,但互斥锁的所有权很容易转移到进程 B(这是一个错误)。这就是为什么它愉快地嗡嗡作响,调用 WaitForSingleObject(获得 WAIT_OBJECT_0 作为返回)和 ReleaseMutex(作为返回获得 TRUE)。

是否可以使用类似于互斥锁的命名同步原语,以便进程 A 中的崩溃将释放互斥锁?

一种解决方案是使用 SEH 并捕获崩溃并释放互斥锁,但我真的希望 Windows 有一个健壮的原语,不会像进程崩溃时那样死锁。

最佳答案

关于互斥锁在 Windows 上的工作方式,您必须在此处做出一些基本假设:

  • 互斥体是引用计数的操作系统对象。它不会消失,直到互斥锁的最后一个句柄关闭
  • 任何在进程终止时未关闭的句柄都会被操作系统关闭,从而减少引用计数
  • 互斥体是可重入的,在同一线程上的互斥体上调用 WaitForSingleObject 成功并且需要与相同数量的 ReleaseMutex 调用进行平衡
  • 当拥有它的线程在没有调用 ReleaseMutex 的情况下终止时,拥有的互斥锁将被放弃。在此状态下对互斥锁调用 WaitForSingleObject 会生成 WAIT_ABANDONED 错误返回代码
  • 它从来都不是操作系统中的错误。

  • 所以你可以根据你的观察得出结论。当 A 崩溃时,互斥锁没有任何 react ,B 仍然有一个句柄。 B 可以注意到 A 崩溃的唯一可能方法是当 A 在它拥有互斥锁时崩溃。发生这种情况的几率非常低,而且很容易观察到,因为 B 会死锁。更有可能的是 B 会很高兴地继续前进,因为它现在完全不受阻碍,没有其他人会再获得互斥锁。

    此外,当 A 重新开始时的死锁证明了您已经知道的事情:B 由于某种原因永久拥有互斥锁。可能是因为它递归地获取了互斥锁。您知道这一点是因为您注意到必须两次调用 ReleaseMutex。这是您需要修复的错误。

    您需要保护自己免受兄弟进程崩溃的影响,并且需要为此编写显式代码。对同级调用 OpenProcess 以获取进程对象的句柄。当进程终止时,句柄上的 WaitForSingleObject 调用将完成。

    关于winapi - 进程崩溃时未释放 Win32 命名互斥锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14985247/

    相关文章:

    c# - 启动启动进程 B 的 Win32 进程 A——获取 B 的 ID/HWND

    C++ - 基本的 WinAPI 问题

    c++ - 从 HGDIOBJ 到 HBRUSH 的转换

    winapi - MB_ERR_INVALID_CHARS 标志是否应该用于 MultiByteToWideChar 的 UTF-8 转换?

    delphi - Delphi win32 应用程序的自安装程序

    c# - WMI ConnectServer 到 ROOT\CIMV2 为 C++ 应用程序返回 'Access Denied' 但对于 C# 应用程序工作正常

    c# - 在 Windows x64 中从句柄获取可执行文件名

    go - 如何管理使用 Win32 API(记事本、Word、Outlook、Chrome 等)打开的应用程序窗口

    c++ - OpenThread 和关闭多个线程句柄

    windows - 在 Windows 上以事务方式写入文件更改