【问题标题】:Windows - How to cleanup shared memory object left by processs terminated abnormally?Windows - 如何清理异常终止的进程留下的共享内存对象?
【发布时间】:2018-11-13 17:15:07
【问题描述】:

我遇到了一个问题,即进程异常终止,因此一些共享资源 (BaseNamedObjects) 未被进程释放。

CreateFileMapping函数返回ERROR_ALREADY_EXISTS表示共享内存已经存在。

在通过 CreateFileMapping 获得 ERROR_ALREADY_EXISTS 后返回一个句柄。 所以我有以下与上述情况相关的查询:

  1. 我们可以使用这个返回的句柄执行清理吗?
  2. 我们可以使用 CreateFileMapping 的句柄返回吗?
  3. 如何清理这样的共享内存对象?

【问题讨论】:

  • 您的诊断似乎不正确。如果所有打开该对象句柄的进程都已终止,那么系统将已经清理它。因此,必须仍然存在一个现有进程,该进程具有该对象的句柄。
  • 如果您不使用OBJ_PERMANENT 创建对象(为此需要使用本机 api 并具有特殊权限 - 所以可以假设不是) - 当对象的所有句柄关闭时,对象将被自动销毁(名称将被删除)和参考发布(参考可以来自部分映射)。不需要做特别的清理。如果您收到ERROR_ALREADY_EXISTS,则并非所有具有此句柄的进程都已终止
  • 您可能只是为您的文件映射对象使用了一个通用名称,而其他人也这样做了。但是如果没有看到minimal reproducible example,我们应该怎么知道呢?
  • 你给共享内存区域命名了吗?如果是这样,您应该可以在Process Explorer 中搜索它(并查看哪些应用程序正在使用它)。

标签: c windows winapi shared-memory resource-cleanup


【解决方案1】:

返回的句柄对您继续使用是完全有效的,您应该在使用完之后像往常一样关闭该句柄。但是,关闭该句柄不会释放内存或执行清理操作:您的新调用增加了对共享资源的引用计数,而关闭只会将其减少回之前的状态。

似乎有其他进程仍在使用共享内存,因为操作系统应该在进程致命终止后恢复它。

您可能需要某种方式来触发其他进程自毁。一种方法是在该地区预留一个小型心跳计数器。如果任何一个进程发现另一个进程最近没有更新其心跳计数,那么它也应该中止,释放共享资源。

可能您的其他进程实际上并未死亡,而是处于致命的循环或无望的等待状态。为了从这种情况中恢复,您可以将所有进程 ID 存储在共享区域中,然后任何有权访问共享区域的新进程都可以 KILL 所有旧参与者。

【讨论】:

    猜你喜欢
    • 2014-12-12
    • 1970-01-01
    • 2013-11-09
    • 1970-01-01
    • 2020-11-04
    • 1970-01-01
    • 1970-01-01
    • 2010-12-14
    • 2018-09-29
    相关资源
    最近更新 更多