在释放Mutex之前调用CloseHandle会发生什么?

6
如果我在线程完成之前调用 CloseHandle 关闭互斥对象,从而还没有调用 ReleaseMutex,那么预期的行为是什么?

这样做的理由是什么? - San Jacinto
@San Jacinto:MTA COM对象有一些正在执行工作的线程,并且没有通过调用CoFreeUnusedLibraries(0, 0)来给予调用者时间,延迟为0,这会调用DllCanUnloadNow,即使互斥锁还没有被释放,也会返回S_OK。 MTA的默认延迟是10分钟,以允许线程完成,但在这种情况下,我必须检查互斥锁以确保它为NULL,否则从DllCanUnloadNow返回S_FALSE。 这可以防止我们遇到的内存访问冲突。现在,等待互斥锁== NULL的问题在于,没有任何东西明确地调用CloseHandle。 - Richard Anthony Freeman-Hein
哇,很棒的解释。我能建议你编辑你的问题,把这些信息包含进去,以便未来的用户参考吗? - San Jacinto
@San Jacinto 我会在我有空闲的时候尽快做...现在是紧要关头。 - Richard Anthony Freeman-Hein
3个回答

13

CloseHandle() 函数会立即销毁传递给它的句柄。如果使用已关闭的互斥体句柄调用 ReleaseMutex() 函数,则会返回错误代码 ERROR_INVALID_HANDLE

如果互斥体有名称,则有一个支持互斥体的单个引用计数内核对象,但是 CreateMutex()OpenMutex() 返回唯一的 HANDLE 值,这些值必须分别关闭。如果创建/打开同名互斥体的多个句柄,则在一个句柄上调用 CloseHandle() 不会影响到同一互斥体的其他句柄。


11

最严重的后果是等待互斥锁的线程被解除阻塞。WaitXxx调用返回WAIT_ABANDONED。此时最好调用TerminateProcess,因为你不知道到底发生了什么。


只有当线程在仍然拥有互斥锁的情况下终止时,才会报告WAIT_ABANDONED。这与提前调用CloseHandle()关闭互斥锁句柄是不同的。 - Remy Lebeau
@Remy - 我认为你混淆了ReleaseMutex()调用所获得的GetLastError()值。我说的是WaitForSingleObject()和相关函数。 - Hans Passant
你认为使用 WaitForSingleObject 来确保线程结束后再调用 CloseHandle 是一个不好的主意吗? - Richard Anthony Freeman-Hein
是的,我已经工作了12个多小时了...我很累。明天我会发布一个片段来展示我的意思,并确保一切都好,但我认为我得到了我的答案。 - Richard Anthony Freeman-Hein
我认为只有在线程在释放互斥锁失败后退出时才是正确的。如果线程继续运行,它可能仍然拥有互斥锁的所有权。 - Harry Johnston
显示剩余2条评论

4
在这种情况下,CloseHandle()确实会销毁句柄,但是当所有句柄都关闭时,互斥对象才会从内存中删除。 因此,通过CloseHandle(handle)您将销毁该句柄,因此ReleaseMutex(handle)将无法工作。但是,互斥体仍然由该线程拥有,没有释放它的方法,影响其他等待互斥锁的线程。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接