WPF内部DeliverEvent读锁和PrivateAddListener写锁导致死锁
1.对失去响应进程创建转储文件
2.配置该进程的pdb文件
3.复制该进程所在机器的系统dll(sos.dll, clr.dll, mscordacwks.dll)
4.配置系统dll的pdb文件路径, 或者直接从msdl.microsoft/download/symbols下载(注意端口是否被封)
分析过程:
1.利用~*e !clrstack
得到UI线程的ID 为12
2.利用~12e !clrstack -p
得到堆栈信息及函数参数值
3.从中发现先申请写锁, 后申请读锁,导致UI死锁
第一个锁CollectionChangedEventManager.DeliverEvent读锁
第二个锁PropertyChangedEventManager.PrivateAddListener写锁
0000000021137b28 000007fef87010b4 [HelperMethodFrame_1OBJ: 0000000021137b28] System.Threading.ReaderWriterLock.AcquireReaderLockInternal(Int32)
0000000021137c50 000007fef3eee179 System.Windows.WeakEventManager.DeliverEvent(System.Object, System.EventArgs)
PARAMETERS:
this (0x0000000021137ce0) = 0x0000000002f45678
sender (0x0000000021137ce8) = 0x00000000039ac078
args (0x0000000021137cf0) = 0x00000000044a2828
.....................省略部分日志信息
000000002113cf78 000007fef879cae7 [HelperMethodFrame_1OBJ: 000000002113cf78] System.Threading.ReaderWriterLock.AcquireWriterLockInternal(Int32)
000000002113d0a0 000007fef3eedf0a System.ComponentModel.PropertyChangedEventManager.PrivateAddListener(System.ComponentModel.INotifyPropertyChanged, System.Windows.IWeakEventListener, System.String)
PARAMETERS:
this = <no data>
source = <no data>
listener = <no data>
propertyName = <no data>
000000002113d120 000007fee7ce8e76 MS.Internal.Data.PropertyPathWorker.ReplaceItem(Int32, System.Object, System.Object)
PARAMETERS:
this = <no data>
k = <no data>
newO = <no data>
parent = <no data>
4. 利用!do分析读锁中DeliverEvent传递的参数args (0x0000000021137cf0) = 0x00000000044a2828
0:000> !do 0x00000000044a2828
Name: System.Collections.Specialized.NotifyCollectionChangedEventArgs
MethodTable: 000007fef6b5ffb8
EEClass: 000007fef6853e90
Size: 48(0x30) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll
Fields:
MT Field Offset Type VT Attr Value Name
000007fef7840c78 40001c7 80 System.EventArgs 0 shared static Empty
>> Domain:Value 00000000007f85a0:0000000002f2a5c8 <<
000007fef6b5cad0 4000674 18 System.Int32 1 instance 4 _action
000007fef782f780 4000675 8 ...Collections.IList 0 instance 0000000000000000 _newItems
000007fef782f780 4000676 10 ...Collections.IList 0 instance 0000000000000000 _oldItems
000007fef782c858 4000677 1c System.Int32 1 instance -1 _newStartingIndex
000007fef782c858 4000678 20 System.Int32 1 instance -1 _oldStartingIndex
5.根据成员_action 为4 查MSDN可知,当时的操作位Rest
public enum NotifyCollectionChangedAction
{
[__DynamicallyInvokable] Add,
[__DynamicallyInvokable] Remove,
[__DynamicallyInvokable] Replace,
[__DynamicallyInvokable] Move,
[__DynamicallyInvokable] Reset,
}
6.通过~12e !dso
得到对象名的堆栈信息
温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/70008.html
- 上一篇:Windows下的Boost库编译
- 下一篇:C#特性类的使用