首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用ReaderWriterLockSlim调试死锁

使用ReaderWriterLockSlim调试死锁
EN

Stack Overflow用户
提问于 2014-09-14 21:14:20
回答 2查看 1.5K关注 0票数 4

我正在调试一个针对.NET 3.5的托管应用程序中的挂起。其中一个线程永远在等待方法System.Threading.ReaderWriterLockSlim.EnterWriteLock。为了找出哪个线程拥有锁,我检查了ReaderWriterLockSlim类的internal member field ReaderWriterCount[] rwc以及它包含的所有ReaderWriterCountRecursiveCounts对象。这些对象包含有关所有线程的信息。除了包含readercount=1的单个对象之外,所有对象都包含writercount=0readercount=0

代码语言:javascript
复制
[53] 0144fc84
    Name: System.Threading.ReaderWriterCount
    MethodTable: 6bb4e930
    EEClass: 6b9ba4d0
    Size: 24(0x18) bytes
     (C:\Windows\assembly\GAC_MSIL\System.Core\3.5.0.0__b77a5c561934e089\System.Core.dll)
    Fields:
          MT    Field   Offset                 Type VT     Attr    Value Name
    55782f94  4000625        c         System.Int32  1 instance       53 threadid
    55782f94  4000626       10         System.Int32  1 instance        1 readercount
    6bb4e930  4000627        4 ...ReaderWriterCount  0 instance 00000000 next
    6bb4e858  4000628        8 ...g.RecursiveCounts  0 instance 0144fc9c rc

AFAIU它意味着MTID为53的线程拥有锁。我用kb转储了它的堆栈(!clrstack失败,因为它不是托管线程),并得到以下结果:

代码语言:javascript
复制
ChildEBP RetAddr  Args to Child              
16eee9b4 765c14ab 00000280 00000000 16eee9fc ntdll!ZwWaitForSingleObject+0x15
16eeea20 778d1194 00000280 00009c40 00000000 KERNELBASE!WaitForSingleObjectEx+0x98
16eeea38 681954d7 00000280 00009c40 00000000 KERNEL32!WaitForSingleObjectExImplementation+0x75
16eeea7c 68195423 00000280 00009c40 00000000 mscorwks!PEImage::LoadImage+0x1af
16eeeacc 68195442 00009c40 00000000 00000000 mscorwks!CLREvent::WaitEx+0x117
16eeeae0 681d95c7 00009c40 00000000 00000000 mscorwks!CLREvent::Wait+0x17
16eeeb60 681d9a55 03376058 00009c40 00000000 mscorwks!ThreadpoolMgr::SafeWait+0x73
16eeebc4 68226508 00000000 00000000 00000000 mscorwks!ThreadpoolMgr::WorkerThreadStart+0x11c
16eefa64 778d338a 04b2e5c8 16eefab0 77e09f72 mscorwks!Thread::intermediateThreadProc+0x49
16eefa70 77e09f72 04b2e5c8 6aecf560 00000000 KERNEL32!BaseThreadInitThunk+0xe
16eefab0 77e09f45 682264c2 04b2e5c8 00000000 ntdll!__RtlUserThreadStart+0x70
16eefac8 00000000 682264c2 04b2e5c8 00000000 ntdll!_RtlUserThreadStart+0x1b

这意味着它是一个Idle CLR Worker Thread

我的第一个想法是,当读取器锁不总是被释放时,应用程序代码中存在一个bug。但这一假设并未得到证实,因为代码在ReaderWriterLockSlim.EnterWriteLock上使用了wrapper,如下所示:

代码语言:javascript
复制
readerWriterLockSlim.EnterReadLock();

try
{
    return executeFunc();
}
finally
{
    readerWriterLockSlim.ExitReadLock();
}

finally块必须保证锁总是会被释放。

有没有想过这种情况是怎么发生的?线程会在获取锁之后但在finally之前以某种方式中止,然后成为空闲线程池线程吗?可能有一些小贴士如何缩小问题范围?

附注:这个死锁只被复制了一次,我只有一个内存转储,因此我不能轻易地说,在锁周围添加跟踪或断点并进行实验。

EN

回答 2

Stack Overflow用户

发布于 2014-09-15 07:36:52

尝试!sosex.dlk和/或!mlock和!mwaits。这应该会告诉您发生了什么。

票数 1
EN

Stack Overflow用户

发布于 2015-02-28 00:08:12

您可能会遇到异步异常(如线程中止),从而跳过最终的代码块。你可以在Some limitations: reliability一节中找到更多关于它的信息。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25833635

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档