使用模拟时,互斥锁创建会挂起

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用模拟时,互斥锁创建会挂起相关的知识,希望对你有一定的参考价值。

在测试应用程序时,我遇到了一个奇怪的行为。一些测试使用模拟以不同的用户身份运行代码,但它们总是挂起,永远不会完成。

经过一番调查后,问题被缩小到使用互斥量。最初,我们使用了基于MSDN documentation的我们自己的模拟代码,但即使使用SimpleImpersonation library,问题仍然存在。以下是重现问题的最小示例:

using (Impersonation.LogonUser(DOMAIN, USER, PASSWORD, LogonType.Interactive))
{
    Console.WriteLine("Impersonated");
    bool mine;
    using (new Mutex(true, "Mutex", out mine))
    {
        if (!mine)
            throw new Exception("Couldn't get mutex");
        Console.WriteLine("Got mutex");
    }
}

Console.WriteLine("Finished");

这永远不会完成,它与互斥锁创建一致。 documentation声明它应该抛出异常或返回一些东西,但不提阻塞。

其他一些观察结果,可能与也可能没有关系:

  • 如果我们“模仿”当前用户,它会立即返回
  • 如果我们运行实际应用程序并以另一个用户身份启动另一个实例,那么一切都按预期工作

可能底层系统资源正在发生,但我们无法弄明白。如何使这项工作?

更新:根据汉斯的评论,我尝试禁用Windows Defender,它没有帮助。这是挂起的地方的堆栈跟踪:

    ntdll.dll!_NtWaitForSingleObject@12()
    KernelBase.dll!_WaitForSingleObjectEx@12()
    mscorlib.ni.dll!719c1867()
    [Frames below may be incorrect and/or missing, native debugger attempting to walk managed call stack]   
    mscorlib.ni.dll!719c1852()
    [Managed to Native Transition]  
    mscorlib.dll!System.Threading.Mutex.CreateMutexHandle(bool initiallyOwned, string name, Microsoft.Win32.Win32Native.SECURITY_ATTRIBUTES securityAttribute, out Microsoft.Win32.SafeHandles.SafeWaitHandle mutexHandle)
        mscorlib.dll!System.Threading.Mutex.MutexTryCodeHelper.MutexTryCode(object userData)
    [Native to Managed Transition]  
    [Managed to Native Transition]  
    mscorlib.dll!System.Threading.Mutex.CreateMutexWithGuaranteedCleanup(bool initiallyOwned, string name, out bool createdNew, Microsoft.Win32.Win32Native.SECURITY_ATTRIBUTES secAttrs)   
    mscorlib.dll!System.Threading.Mutex.Mutex(bool initiallyOwned, string name, out bool createdNew, System.Security.AccessControl.MutexSecurity mutexSecurity) 
    mscorlib.dll!System.Threading.Mutex.Mutex(bool initiallyOwned, string name, out bool createdNew)    
    MutexImpersonationTest.exe!MutexImpersonationTest.Program.Main(string[] args) Line 16   
答案

看起来获取Mutex的代码陷入了无限循环,在我的测试中,它在new Mutex(...)的调用中将一个核心固定在100%。

原因似乎是框架代码首先尝试调用Win32 CreateMutex,如果失败并显示“Access Denied”错误,则尝试调用OpenMutex。如果OpenMutex调用失败并显示错误指示互斥锁不存在,则它会再次重复整个过程,因此如果互斥锁不存在则会陷入无限循环。

根据CreateMutex documentation,这本质上是正确的方法,但似乎并没有考虑到最初的CreateMutex因访问被拒绝失败而不是由于现有互斥锁的权限而导致的情况。

当我尝试它时似乎有效的一件事是将互斥锁名称加上“Global ”的前缀,希望这对你来说是一个合适的解决方法。

以上是关于使用模拟时,互斥锁创建会挂起的主要内容,如果未能解决你的问题,请参考以下文章

冻结(挂起)会发生在不使用互斥锁、信号量等的线程不安全代码中吗?

iPhone 应用程序在从后台进入前台时会挂起/阻止 UI 几秒钟

复制/粘贴代码时Eclipse会挂起

在服务中删除和创建性能计数器时,它可能会挂起该服务

LockSupport.java 中的 FIFO 互斥代码片段

为啥 iOS 应用程序图标在 iPhone 6 plus 上安装时会挂起并创建另一个安装图标?