2014-02-26 70 views
4

目前我正在分析一個包含WinDbg的轉儲。確定哪種方法持有ReaderWriterLockSlim WriteLock

我跑以下命令(以下Tess' incredible walkthrough):

~* e !clrstack 

記載了我的所有線程的所有堆棧。有300級或多或少相同的堆棧運行的線程,所以我只是一個印刷這裏的堆...

OS Thread Id: 0x107c (166) 
Child SP  IP Call Site 
2bc1e654 77c1015d [HelperMethodFrame_1OBJ: 2bc1e654] System.Threading.WaitHandle.WaitOneNative(System.Runtime.InteropServices.SafeHandle, UInt32, Boolean, Boolean) 
2bc1e720 6b2e6dd2 System.Threading.WaitHandle.InternalWaitOne(System.Runtime.InteropServices.SafeHandle, Int64, Boolean, Boolean) 
2bc1e73c 6b2e6d9c System.Threading.WaitHandle.WaitOne(Int32, Boolean) 
2bc1e750 727f4baa System.Threading.ReaderWriterLockSlim.WaitOnEvent(System.Threading.EventWaitHandle, UInt32 ByRef, TimeoutTracker) 
2bc1e78c 729bc154 System.Threading.ReaderWriterLockSlim.TryEnterUpgradeableReadLockCore(TimeoutTracker) 
2bc1e7b8 725d250c System.Threading.ReaderWriterLockSlim.TryEnterUpgradeableReadLock(TimeoutTracker) 
** MORE LINES ** 

然後我做了以下內容:

> ~166s 
eax=00000000 ebx=2bc1e444 ecx=00000000 edx=00000000 esi=00000001 edi=00000000 
eip=77c1015d esp=2bc1e3f4 ebp=2bc1e490 iopl=0   nv up ei pl zr na pe nc 
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b    efl=00000246 
ntdll!NtWaitForMultipleObjects+0x15: 
77c1015d 83c404   add  esp,4 

然後我一直在尋找在這個主題中的所有實例:

> !dso 
OS Thread Id: 0x107c (166) 
ESP/REG Object Name 
** MORE LINES ** 
2BC1E7D0 039ec48c System.Threading.ReaderWriterLockSlim 
** MORE LINES ** 

然後我就先在ReaderWriterLockSlim -instance的更多信息:

> !do 039ec48c 
Name:  System.Threading.ReaderWriterLockSlim 
MethodTable: 725ebda4 
EEClass:  724543bc 
Size:  68(0x44) bytes 
File:  C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Core\v4.0_4.0.0.0__b77a5c561934e089\System.Core.dll 
Fields: 
     MT Field Offset     Type VT  Attr Value Name 
6b3b8138 4000755  3c  System.Boolean 1 instance  0 fIsReentrant 
6b3c3aa4 4000756  1c   System.Int32 1 instance  0 myLock 
6b3c7ae4 4000757  20  System.UInt32 1 instance  0 numWriteWaiters 
6b3c7ae4 4000758  24  System.UInt32 1 instance  0 numReadWaiters 
6b3c7ae4 4000759  28  System.UInt32 1 instance  0 numWriteUpgradeWaiters 
6b3c7ae4 400075a  2c  System.UInt32 1 instance  348 numUpgradeWaiters 
6b3b8138 400075b  3d  System.Boolean 1 instance  0 fNoWaiters 
6b3c3aa4 400075c  30   System.Int32 1 instance  366 upgradeLockOwnerId 
6b3c3aa4 400075d  34   System.Int32 1 instance  366 writeLockOwnerId 
6b3c0ac0 400075e  c ...g.EventWaitHandle 0 instance 00000000 writeEvent 
6b3c0ac0 400075f  10 ...g.EventWaitHandle 0 instance 00000000 readEvent 
6b3c0ac0 4000760  14 ...g.EventWaitHandle 0 instance 08188858 upgradeEvent 
6b3c0ac0 4000761  18 ...g.EventWaitHandle 0 instance 00000000 waitUpgradeEvent 
6b3b821c 4000763  4   System.Int64 1 instance 231 lockID 
6b3b8138 4000765  3e  System.Boolean 1 instance  0 fUpgradeThreadHoldingRead 
6b3c7ae4 4000766  38  System.UInt32 1 instance 2147483649 owners 
6b3b8138 4000767  3f  System.Boolean 1 instance  0 fDisposed 
6b3b821c 4000762  3e0   System.Int64 1 shared static s_nextLockID 
    >> Domain:Value 01742528:NotInit 01783fb8:NotInit 1268c9d8:NotInit << 
725fd46c 4000764  4 ...ReaderWriterCount 0 shared TLstatic t_rwc 
    >> Thread:Value << 

我對the information on this page = 0x80000001

private const uint WRITER_HELD = 0x80000000; 
private const uint WAITING_WRITERS = 0x40000000; 
private const uint WAITING_UPGRADER = 0x20000000; 

匹配的owners(2147483649)的價值,但我怎麼能確定哪些持有鎖的線程?

回答

3

如果遇到死鎖,可以使用SOSEx!dlk命令,該命令爲您完成所有工作。

*DEADLOCK DETECTED* 
CLR thread 0x4 holds the Writer lock on ReaderWriterLockSlim 02712580 
...and is waiting for a Reader lock on ReaderWriterLockSlim 0271253c 
CLR thread 0x3 holds the Writer lock on ReaderWriterLockSlim 0271253c 
...and is waiting for a Reader lock on ReaderWriterLockSlim 02712580 
CLR Thread 0x4 is waiting at System.Threading.WaitHandle.InternalWaitOne(System.Runtime.InteropServices.SafeHandle, Int64, Boolean, Boolean)(+0x1f IL,+0x22 Native) 
CLR Thread 0x3 is waiting at System.Threading.WaitHandle.InternalWaitOne(System.Runtime.InteropServices.SafeHandle, Int64, Boolean, Boolean)(+0x1f IL,+0x22 Native) 

如果沒有死鎖,你仍然可以使用SOSEx,但​​鍵入!mlocks。輸出看起來像這樣,所以你得到所有不同的線程號和鎖的類型。

0:012> !mlocks 
Examining SyncBlocks... 
Scanning for ReaderWriterLock instances... 
Scanning for holders of ReaderWriterLock locks... 
Scanning for ReaderWriterLockSlim instances... 
Scanning for holders of ReaderWriterLockSlim locks... 
Examining CriticalSections... 

ClrThread DbgThread OsThread LockType Lock  LockLevel 
---------------------------------------------------------------------- 
0x1  0   0x1460  thinlock 02718bcc (recursion:0) 
0x5  6   0x1e80  RWLock  027125f0 Writer   
0x8  9   0x22ac  CritSect 027124c0     
0x9  10   0x27b8  SyncBlock 0045f4e8     
0xa  11   0x33f8  SyncBlock 0045f4b4     
0x7  8   0x388c  CritSect 027124a0     
0x4  5   0x3d20  RWLockSlim 02712580 Writer   
0x3  4   0x3e44  RWLockSlim 0271253c Writer   
0x6  7   0x4704  RWLock  027125c4 Writer   

如果啓用了DML,你甚至可以點擊鎖定列賦予更多信息的鏈接。如果你不喜歡DML,你也可以輸入!rwlock <lock>

+0

+,呵呵...很酷的東西!唯一的事情是......我正在繞過11 **千行**作爲輸出。太難以解釋 - 但是當我搜索'RwLockSlim'時,我得到所需的行... –

+2

@AndreasNiedermair:'.shell -ci「!mlocks -d」find「Writer」'可能會幫助如果爲讀者輸出的是「讀者」(我現在不能嘗試) –

+0

就像一個老闆......! –

2

我做了一些更多的研究,並反編譯ReaderWriterLockSlim並確定writeLockOwnerIdupgradeLockOwnerId的含義:它們實際上是相應方法內線程的託管線程ID。

不幸的是你有,做,以確定此託管線程ID的順序:

> !threads 
ThreadCount:  371 
UnstartedThread: 0 
BackgroundThread: 371 
PendingThread: 0 
DeadThread:  0 
Hosted Runtime: no 
                     Lock 
     ID OSID ThreadOBJ State GC Mode  GC Alloc Context Domain Count Apt Exception 
** MORE LINES ** 
381 366 1c0c 1e1fca78 1029220 Preemptive 3E46102C:00000000 01783fb8 2  MTA (Threadpool Worker) 
** MORE LINES ** 

在此之後,你可以簡單地做:

> ~381s 
eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 esi=0000432d edi=4519d490 
eip=77c0f8d1 esp=4519d448 ebp=4519d4b4 iopl=0   nv up ei pl zr na pe nc 
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b    efl=00000246 
ntdll!ZwWaitForSingleObject+0x15: 
77c0f8d1 83c404   add  esp,4 

> !clrstack 
OS Thread Id: 0x1c0c (381) 
Child SP  IP Call Site 
** MORE LINES ** 
4519da08 69f35592 System.Data.SqlClient.SqlCommand.ExecuteReader(System.Data.CommandBehavior, System.String) 
** MORE LINES ** 

的Et瞧:線程,持有可升級的鎖,目前正在執行一些sql。