【问题标题】:Information about object that thread is waiting for有关线程正在等待的对象的信息
【发布时间】:2010-10-10 19:29:38
【问题描述】:

如果我有以下堆栈跟踪,我看到一个线程正在等待某个锁。如何获取有关此线程正在等待的对象的信息?我在想我应该能够使用 SyncBlk 命令,但似乎它只能提供有关锁及其所有者线程的信息。

0:000> !CLRStack  
OS Thread Id: 0x25a8 (0)  
ESP       EIP       
001af038 77455e74 [GCFrame: 001af038]   
001af108 77455e74 [HelperMethodFrame_1OBJ: 001af108] System.Threading.Monitor.Enter(System.Object)  
001af160 00290192 ConsoleApplication1.MyClass.Main(System.String[])  
001af3c0 70fc1b4c [GCFrame: 001af3c0]   

【问题讨论】:

  • 您不能从 Visual Studio 或其他 IDE 进行调试吗?如果设置了断点,则可以通过检查堆栈指针来浏览所有等待它的线程
  • 不,我正在查看转储文件
  • 如果您正在寻找一种方法来获取线程等待的本机句柄(实际的内核对象),那么您可能会发现这篇文章很有用:blog.liranchen.com/2010/07/monitors-locking-primitive.html

标签: sos windb


【解决方案1】:

在 .NET 中,方法的引用参数在调用方法之前被压入堆栈,因此如果您为相关线程执行 !dso,您应该在堆栈顶部找到 Monitor.Enter 的参数。那就是对象,代码正试图锁定。

如果您将其地址与!threads 的输出相关联,您可以找出当前哪个线程拥有此锁(如果有)。

【讨论】:

    【解决方案2】:

    要找出线程正在等待哪个对象,您必须进行一些调试。

    首先,从您拥有的堆栈跟踪开始:

    0:000> !CLRStack
    操作系统线程 ID:0x25a8 (0)
    ESP EIP
    001af038 77455e74 [GCFrame: 001af038]
    001af108 77455e74 [HelperMethodFrame_1OBJ: 001af108] System.Threading.Monitor.Enter(System.Object)
    001af160 00290192 ConsoleApplication1.MyClass.Main(System.String[])
    001af3c0 70fc1b4c [GCFrame: 001af3c0]

    找出调用 Monitor.Enter() 的框架。在这种情况下,它是 MyClass::Main(string [] args)

    001af160 00290192 ConsoleApplication1.MyClass.Main(System.String[])

    现在你需要反汇编调用者。使用 !sos.u [eip] 来做到这一点。

    
    0:000> !u 00d10177 
    Normal JIT generated code
    Program.Main(System.String[])
    Begin 00d100f8, size 9d
    00d100f8 55              push    ebp
    00d100f9 8bec            mov     ebp,esp
    00d100fb 83ec10          sub     esp,10h
    00d100fe 894dfc          mov     dword ptr [ebp-4],ecx
    00d10101 833de430970000  cmp     dword ptr ds:[9730E4h],0
    00d10108 7405            je      00d1010f
    00d1010a e802a63b79      call    mscorwks!JIT_DbgIsJustMyCode (7a0ca711)
    00d1010f 33d2            xor     edx,edx
    00d10111 8955f8          mov     dword ptr [ebp-8],edx
    00d10114 90              nop
    *** WARNING: Unable to verify checksum for C:\WINDOWS\assembly\NativeImages_v2.0.50727_32\mscorlib\7bffd7ff2009f421fe5d229927588496\mscorlib.ni.dll
    00d10115 b9fc7e3179      mov     ecx,offset mscorlib_ni+0x257efc (79317efc) (MT: System.Threading.ThreadStart)
    00d1011a e8ad1fc5ff      call    009620cc (JitHelp: CORINFO_HELP_NEWSFAST_CHKRESTORE)
    00d1011f 8945f4          mov     dword ptr [ebp-0Ch],eax
    00d10122 b858c09700      mov     eax,97C058h
    00d10127 50              push    eax
    00d10128 6864203b00      push    3B2064h
    00d1012d 8b4df4          mov     ecx,dword ptr [ebp-0Ch]
    00d10130 33d2            xor     edx,edx
    00d10132 e8b9a45678      call    mscorlib_ni+0x1ba5f0 (7927a5f0) (System.MulticastDelegate.CtorOpened(System.Object, IntPtr, IntPtr), mdToken: 060003bf)
    00d10137 b9f8103379      mov     ecx,offset mscorlib_ni+0x2710f8 (793310f8) (MT: System.Threading.Thread)
    00d1013c e8c3c41679      call    mscorwks!JIT_NewFast (79e7c604)
    00d10141 8945f0          mov     dword ptr [ebp-10h],eax
    00d10144 8b55f4          mov     edx,dword ptr [ebp-0Ch]
    00d10147 8b4df0          mov     ecx,dword ptr [ebp-10h]
    00d1014a e8e1685c78      call    mscorlib_ni+0x216a30 (792d6a30) (System.Threading.Thread..ctor(System.Threading.ThreadStart), mdToken: 060012ab)
    00d1014f 8b45f0          mov     eax,dword ptr [ebp-10h]
    00d10152 8945f8          mov     dword ptr [ebp-8],eax
    00d10155 8b4df8          mov     ecx,dword ptr [ebp-8]
    00d10158 3909            cmp     dword ptr [ecx],ecx
    00d1015a e861695c78      call    mscorlib_ni+0x216ac0 (792d6ac0) (System.Threading.Thread.Start(), mdToken: 060012b1)
    00d1015f 90              nop
    00d10160 8b0d30202e02    mov     ecx,dword ptr ds:[22E2030h] ("Acquiring lock")
    00d10166 e89d38a878      call    mscorlib_ni+0x6d3a08 (79793a08) (System.Console.WriteLine(System.String), mdToken: 060007c8)
    00d1016b 90              nop
    00d1016c 8b0dfc1e2e02    mov     ecx,dword ptr ds:[22E1EFCh] (Object: SyncBlock)
    00d10172 e8ae281679      call    mscorwks!JIT_MonEnterWorker (79e72a25)
    >>> 00d10177 90              nop
    00d10178 8b0d34202e02    mov     ecx,dword ptr ds:[22E2034h] ("Releasing lock")
    00d1017e e88538a878      call    mscorlib_ni+0x6d3a08 (79793a08) (System.Console.WriteLine(System.String), mdToken: 060007c8)
    00d10183 90              nop
    00d10184 8b0dfc1e2e02    mov     ecx,dword ptr ds:[22E1EFCh] (Object: SyncBlock)
    00d1018a e8102b1679      call    mscorwks!JIT_MonExitWorker (79e72c9f)
    00d1018f 90              nop
    00d10190 90              nop
    00d10191 8be5            mov     esp,ebp
    00d10193 5d              pop     ebp
    00d10194 c3              ret
    
    

    注意调用站点。此时您有以下调试信息:

    00d1016c 8b0dfc1e2e02 mov ecx,dword ptr ds:[22E1EFCh](对象:SyncBlock) 00d10172 e8ae281679 调用 mscorwks!JIT_MonEnterWorker (79e72a25) >>> 00d10177 90 无 00d10178 8b0d34202e02 mov ecx,dword ptr ds:[22E2034h](“释放锁”) 00d1017e e88538a878 调用 mscorlib_ni+0x6d3a08 (79793a08) (System.Console.WriteLine(System.String), mdToken: 060007c8) 00d10183 90 无

    就在调用 JitMon::Enter() 之前,您会看到对象的地址被移动到 ECX 寄存器中。这是您的线程正在等待的对象。

    【讨论】:

    • 只是为了确保我做对了,你在说 00d1016c 8b0dfc1e2e02 mov ecx,dword ptr ds:[22E1EFCh] (Object: SyncBlock) 这意味着对象线程正在等待是一个在 22E1EFCh 正确吗?
    • 似乎也像使用 !dso 的方法,Brian 建议也给我正确的对象。关于使用这种方法的利弊与 Brian 建议的任何想法?
    • 是的,没错。正确的对象位于“!do poi(22E1EFCh)”。 !dso 还可以为您提供您正在等待的对象。但是,如果您在线程上有多个锁,您可能不得不求助于反汇编。无论如何,能够阅读一些反汇编是很好的:)
    【解决方案3】:

    我在你的另一个 SO 问题中给出了答案:

    How to debug managed deadlocks.

    【讨论】:

    • 使用 SyncBlk 我可以获得关于锁及其所有者的信息。我在这里要做的是找出这个线程正在等待什么对象。因此,例如在上面的示例中,通过查看堆栈跟踪,该线程正在等待锁定。我怎么知道这个线程从这里等待哪个对象。你知道我的意思吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-30
    • 2020-10-24
    • 2012-06-29
    • 1970-01-01
    • 1970-01-01
    • 2010-11-11
    • 1970-01-01
    相关资源
    最近更新 更多